牛客算法周周练7 ACDE
闲扯下:A,E题解...写在最后,然后B....不会,不过好像大不了硬写一个搜索好像也能过,题都没咋读懂
先写D题,C当时没有dp出来
D
D题其实算是求割边数量的板子题,什么是割边呢?即比如我们把一个图中一条边去掉,就会变成两个图,但是如果我们要去掉的那条边在自环上,就不存在割边
如果知道割边的数量,那么答案即总边数减去割边数,所以就是一个板子题.........
然后这个割边咋求具体看代码
时间复杂度:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 50;
int low[N], num[N], dfn; //dfn记录递归深度,用于给num赋值
bool iscut[N];
vector<int> G[N];
int ans; //存图
void dfs(int u, int fu) //u的父节点是fu
{
low[u] = num[u] = ++dfn; //随着深度增加,low和num增大
int child = 0;
for (int i = 0; i < G[u].size(); i++) //处理u的所有邻居
{
int v = G[u][i];
if (!num[v]) //没被访问过
{
child++;
dfs(v, u);
low[u] = min(low[u], low[v]); //用后代返回值更新low
if (low[v] > num[u])
ans++; //记录割边数量
}
else if (num[v] < num[u] && v != fu) //处理回退边
low[u] = min(low[u], num[v]);
}
}
int main()
{
int n, m;
cin >> n >> m;
//初始化
memset(low, 0, sizeof(low));
memset(num, 0, sizeof(num));
memset(iscut, false, sizeof(iscut));
for (int i = 0; i < N; i++)
G[i].clear();
dfn = 0;
for (int i = 0; i < m; i++)
{
int x, y;
cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1, -1);
cout << m - ans << endl;
return 0;
}C
这没啥说的dp
这个就不献丑了,转载了一下当时牛客官方给的题解
#include<bits/stdc++.h>
using namespace std;
int dp[2][405][405];
char s[406];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
scanf("%s",s+1);
memset(dp,0x3f,sizeof dp);
dp[0][0][0]=0;
for(int i=1;i<=n;i++){
memset(dp[i%2],0x3f,sizeof dp[i%2]);
for(int j=i;j>=0;j--){//总天数
for(int l=0;l<=j;l++){//连续工作天数
dp[i%2][j][0]=min(dp[i%2][j][0],dp[(i+1)%2][j][l]);
if(s[i]=='1'&&l){
dp[i%2][j][l]=min(dp[i%2][j][l],dp[(i+1)%2][j-1][l-1]+l);
}
}
}
}
int ans=0;
for(int i=0;i<=n;i++){
for(int j=0;j<=i;j++){
if(dp[n%2][i][j]<=k){
ans=max(ans,i);
}
}
}
cout<<ans<<endl;
}A,E
然后再说下A,E
先说E题比较指数大小可以转换成比较对数大小
A题排序,比如起点在左下角,那么假设我们先走到最右上的那个点,中间能走到的走一下,然后剩下的点,在回起点的时候,再走
查看9道真题和解析