zoukankan      html  css  js  c++  java
  • 【CodeForces】915 D. Almost Acyclic Graph 拓扑排序找环

    【题目】D. Almost Acyclic Graph

    【题意】给定n个点的有向图(无重边),问能否删除一条边使得全图无环。n<=500,m<=10^5。

    【算法】拓扑排序

    【题解】找到一个简单环,则欲删除的边一定经过该环。尝试环上的每一条边(至多n条边)后再次拓扑排序判断全图是否有环。

    拓扑排序后定位到简单环:剩余图是环+环内DAG,DFS过程中将走入死路的点标-1,访问过标1,找到访问过的点就是简单环。换起始点直到找到环为止。

    复杂度O(nm)。

    #include<cstdio>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int maxn=600,maxm=100010;
    struct edge{int v,from;}e[maxm];
    int map[maxn][maxn],tot,cnt,n,m,first[maxn],p,vis[maxn],in[maxn],deg[maxn],suc[maxn];
    queue<int>Q;
    void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;in[v]++;}
    void dfs(int x,int fa){
        if(p||vis[x]==-1)return;
        if(vis[x]==1){p=x;suc[fa]=x;return;}
        vis[x]=1;
        for(int i=first[x];i;i=e[i].from)if(deg[e[i].v]>0){
            dfs(e[i].v,x);
            if(p){if(fa&&!suc[p])suc[fa]=x;break;}
        }
        if(!p)vis[x]=-1;
    }
    bool solve(int o){
        cnt=0;
        for(int i=1;i<=n;i++){deg[i]=in[i];if(i==e[o].v)deg[i]--;if(deg[i]==0)Q.push(i),cnt++;}
        while(!Q.empty()){
            int x=Q.front();Q.pop();
            for(int i=first[x];i;i=e[i].from)if(i!=o&&--deg[e[i].v]==0)Q.push(e[i].v),cnt++;
        }
        if(cnt==n)return 1;
        return 0;
    }    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            insert(u,v);map[u][v]=tot;
        }
        cnt=0;
        for(int i=1;i<=n;i++){deg[i]=in[i];if(in[i]==0)Q.push(i),cnt++;}
        while(!Q.empty()){
            int x=Q.front();Q.pop();
            for(int i=first[x];i;i=e[i].from)if(--deg[e[i].v]==0)Q.push(e[i].v),cnt++;
        }
        if(cnt==n){printf("YES");return 0;}
        for(int i=1;i<=n;i++)if(deg[i]>0&&!p)dfs(i,0);
        int pp=p;
        do{
            if(solve(map[p][suc[p]])){printf("YES");return 0;}
            p=suc[p];
        }while(p!=pp);
        printf("NO");
        return 0;
    }
    View Code

    另一种解法:枚举点i,in[i]--,拓扑排序找环。这样相当于删除一条指向n的边后全图找环。

  • 相关阅读:
    filter()函数
    递归算法
    日志模块nb_log
    sys.argv[]简单阐述
    DB2中字符、数字和日期类型之间的转换
    Java 连接 Hive的样例程序及解析
    对hadoop namenode -format执行过程的探究
    想要成为牛人、大佬,那请至少拥有这12项技能!
    形象决定你的收入,别问为什么!
    年轻人,能用钱解决的,绝不要花时间(转)
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8287645.html
Copyright © 2011-2022 走看看