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的边后全图找环。

  • 相关阅读:
    每天一个linux命令(40):wc命令
    每天一个linux命令(39):grep 命令
    每天一个linux命令(38):cal 命令
    每天一个linux命令(37):date命令
    每天一个linux命令(36):diff 命令
    每天一个linux命令(35):ln 命令
    [android] Activity 的生命周期 以及横屏竖屏切换时 Activity 的状态变化
    Android onConfigurationChanged 不执行
    faster-rcnn anchor 介绍
    Faster-rcnn centos tensorflow
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8287645.html
Copyright © 2011-2022 走看看