• Codeforces 999E【Reachability from the Capital】(强连通缩点)


    CF2000分

    题意:给你n个点m条单向边和根节点root,问root要能成功访问所有点所需要添加的边数。

    题解:

    1.(官方题解)显然强联通缩点。缩点完后对每个点的入度进行统计,如果入度是0就++ans

    2.(我的解法)强连通缩点完后,因为点数和边数最多就5000个点,所以可以O(n^2)暴力跑dfs求出每个点可以到达的点有哪些,用vector记录。然后因为包含关系,所以我们对vector按大小从大到小排序。看每个点是否被访问过,如果没被访问过就把vector里的所有点都访问一下,时间复杂度大概是O(n^2)。比官方题解慢了很多但是就这个题而言可以过

    我就附上我自己的AC代码吧

    #include<bits/stdc++.h>
    #pragma GCC optimize(2)
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=5e3+5;
    int tot,head[maxn];
    struct E{
        int to,next;
    }edge[maxn<<1];
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int n,m,root,u[maxn],v[maxn],id[maxn],low[maxn],dfn[maxn],vis[maxn],tott,cnt;
    stack<int> s;
    void tarjan(int x){
        low[x]=dfn[x]=++tott;
        s.push(x);vis[x]=1;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(vis[v]){
                low[x]=min(low[x],dfn[v]);
            }
        }
        if(low[x]==dfn[x]){
            cnt++;
            while(1){
                int now=s.top();
                s.pop();
                vis[now]=0;
                id[now]=cnt;
                if(now==x) break;
            }
        }
    }
    vector<vector<int> > vec(maxn);
    void bfs(int x){
        set<int> s;
        queue<int> q;q.push(x);
        while(!q.empty()){
            int now=q.front();q.pop();
            s.insert(now);vec[x].push_back(now);
            for(int i=head[now];i!=-1;i=edge[i].next){
                int v=edge[i].to;
                if(s.count(v)) continue;
                s.insert(v);
                q.push(v); 
            }
        }    
    }
    bool cmp(vector<int>&a,vector<int>&b){
        return a.size()>b.size();
    }
    int viss[maxn];
    int main(){
        scanf("%d%d%d",&n,&m,&root);mem(head,-1);tott=cnt=0;
        rep(i,1,m){
            scanf("%d%d",&u[i],&v[i]);
            add(u[i],v[i]);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]) tarjan(i);
        }
        mem(head,-1);tot=0;
        for(int i=1;i<=m;i++){
            int uu=id[u[i]],vv=id[v[i]];
            if(uu==vv) continue;
            add(uu,vv);
        }
        root=id[root];
        for(int i=1;i<=cnt;i++){
            bfs(i);
        }
        int ans=0;
        for(int i=0;i<vec[root].size();i++){
            viss[vec[root][i]]=1;
        }
        sort(vec.begin(),vec.end(),cmp);
        for(int i=0;i<cnt;i++){
            if(viss[vec[i][0]]) continue;
            ++ans;
            for(auto it:vec[i]) viss[it]=1;
        }
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    iOS.TextKit.02.文字图片混合排版
    翻翻乐游戏源码
    Dribbble客户端应用源码
    安卓版谍报馆客户端应用源码
    多文件上传 iOS功能
    最新模仿ios版微信应用源码
    类似QQ的应用毗邻(Pilin)即时聊天源码
    很类似新版天天动听音乐播放器安卓应用源码
    高仿安卓跑酷游戏源码
    类似美丽说应用源码带有详细开发说明文档
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13854288.html
Copyright © 2020-2023  润新知