牛客算法周周练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题排序,比如起点在左下角,那么假设我们先走到最右上的那个点,中间能走到的走一下,然后剩下的点,在回起点的时候,再走

全部评论

相关推荐

点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务