zoukankan      html  css  js  c++  java
  • Codeforces 505D

    D - Mr. Kitayuta's Technology

    题意:给n个点,然后给出m个条件a、b,表示a可到达b,求最少需要建多少条有向边才能满足所有条件

    思路:按所给的条件建有向图,可以发现,每一个联通块都是一个弱联通图,若一个m个点的联通块,如果没有环的话最少需要m-1条有向边,即连成一条链,若存在环,只需要m条边就可以连成一个强联通图,自然会满足联通块的所有条件,那么用拓扑判断有向环即可,注意建图的时候还是要建无向图,但是入度只记录条件给的边,因为如果建无向图,那么在dfs的时候不一定可以一次找到弱联通块所有的点,比如 1 2, 2 1这样的数据,所以建双向边,在每次dfs的时候把入度为0的点加入拓扑队列即可

    AC代码:

    #include "iostream"
    #include "string.h"
    #include "stack"
    #include "queue"
    #include "string"
    #include "vector"
    #include "set"
    #include "map"
    #include "algorithm"
    #include "stdio.h"
    #include "math.h"
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ll long long
    #define endl ("
    ")
    #define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
    #define mem(a,x) memset(a,x,sizeof(a))
    #define mp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define ft first
    #define sd second
    #define lrt (rt<<1)
    #define rrt (rt<<1|1)
    using namespace std;
    const long long INF = 1e18+1LL;
    const int inf = 1e9+1e8;
    const int N=1e5+100;
    const ll mod=1e9+7;
    
    int in[N],head[N],to[N<<1],nex[N<<1],tot=1;
    int n,m,ans,vis[N],mk[N];
    queue<int> Q;
    void add(int u, int v){
        to[tot]=v;
        nex[tot]=head[u];
        head[u]=tot++;
    }
    int dfs(int u){
        int ret=1; vis[u]=1;
        if(in[u]==0){
            Q.push(u);
            mk[u]=1;
        }
        for(int i=head[u]; i!=-1; i=nex[i]){
            int v=to[i];
            if(!vis[v]) ret+=dfs(v);
        }
        return ret;
    }
    bool topo(int u, int c){
        int k=0;
        while(!Q.empty()){
            int now=Q.front(); Q.pop(), k++;
            for(int i=head[now]; i!=-1; i=nex[i]){
                int v=to[i]; in[v]--;
                if(!mk[v] && in[v]==0){
                    Q.push(v);
                    mk[v]=1;
                }
            }
        }
        return k==c;
    }
    int main(){
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        mem(head,-1);
        cin>>n>>m;
        for(int _=1; _<=m; ++_){
            int u, v; cin>>u>>v;
            add(u,v); add(v,u); in[v]++;
        }
        for(int i=1; i<=n; ++i){
            if(!vis[i] && in[i]==0){
                while(!Q.empty()) Q.pop();
                int c=dfs(i);
                if(topo(i,c)) ans+=c-1;
                else ans+=c;
            }
        }
        for(int i=1; i<=n; ++i){
            if(!vis[i]) ans++;
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    软件测试笔记(二):软件测试流程
    关于Kotlin中日志的使用方法
    Github Pages+Gridea设置DisqusJS评论
    软件测试笔记(一):软件测试概论
    CVPR2021| TimeSformer-视频理解的时空注意模型
    经典论文系列 | Group Normalization & BN的缺陷
    经典论文系列 | 重新思考在ImageNet上的预训练
    CVPR2021 | 华为诺亚实验室提出Transformer in Transformer
    经典论文系列| 实例分割中的新范式-SOLO
    我们真的需要模型压缩吗
  • 原文地址:https://www.cnblogs.com/max88888888/p/7342205.html
Copyright © 2011-2022 走看看