HDU3342有向图判圈DFS&&拓扑排序法

Posted xiaowuga

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3342有向图判圈DFS&&拓扑排序法相关的知识,希望对你有一定的参考价值。

HDU3342 Legal or Not

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3342

题目意思:一群大牛互相问问题,大牛有不会的,会被更厉害的大牛解答,更厉害的大牛是会的东西比大牛多,但是有的时候更厉害的大牛会装弱,出来问问题,这样就被大牛解答了。这样就形成了一个圈。题目的意思就是让你在一个有向图里面判断是否存在环。我们可以通过dfs和拓扑排序两种方法。

DFS的代码:

//Author: xiaowuga
#include <bits/stdc++.h>
#define maxx INT_MAX
#define minn INT_MIN
#define inf 0x3f3f3f3f
const long long N=100000+10; 
using namespace std;
typedef long long L;
vector<int>q;
vector<int>p[N];
int in[N];
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    int n,m;
    while(cin>>n>>m){
        q.clear();
        memset(in,0,sizeof(in));
        for(int i=1;i<=n;i++) p[i].clear();
        q.clear();
        int reward[N];
        for(int i=1;i<=n;i++) reward[i]=888;
        for(int i=0;i<m;i++){
            int a,b;
            cin>>a>>b;
            p[b].push_back(a);
            in[a]++;
        }
        int ct=0,ans=0;
        for(int i=1;i<=n;i++) if(!in[i]) {q.push_back(i);ans+=reward[i];}
        while(q.size()!=0){
            int t=q.back();q.pop_back();
            ct++;
            for(int i=0;i<p[t].size();i++){
                int x=p[t][i];
                if(--in[x]==0){
                    q.push_back(x);
                    reward[x]=max(reward[x],reward[t]+1);
                    ans+=reward[x];
                }
                else{
                    reward[x]=max(reward[x],reward[t]+1);
                }
            }
        }
        if(ct!=n){
            cout<<-1<<endl;
        }
        else cout<<ans<<endl;
    }
    return 0;
}

dfs的思路,就是一路遍历做标记,然后如果遍历到已经遍历过的就说明存在环,但是一找到环就可以break,跳出,结束dfs,可以剪枝,不然会超时,因为一个点可能遍历很多遍,所以dfs是比较慢的。

 

拓扑排序的做法

为什么可以判圈我在我的另外一篇博文里面已经说清楚了:http://www.cnblogs.com/xiaowuga/p/7218382.html

还是把一个环缩成一个点思想,环上的大小关系的等价的,从而无法遍历所有的点,通过遍历点的数量来判断是否形成环。

代码:

//Author: xiaowuga
#include <bits/stdc++.h>
#define maxx INT_MAX
#define minn INT_MIN
#define inf 0x3f3f3f3f
const long long N=100000+10; 
using namespace std;
typedef long long L;
vector<int>q;
vector<int>p[N];
int in[N];
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    int n,m;
    while(cin>>n>>m&&n&&m){
        q.clear();
        memset(in,0,sizeof(in));
        for(int i=0;i<n;i++) p[i].clear();
        q.clear();
        for(int i=0;i<m;i++){
            int a,b;
            cin>>a>>b;
            p[b].push_back(a);
            in[a]++;
        }
        int ct=0;
        for(int i=0;i<n;i++) if(!in[i]) {q.push_back(i);}
        while(q.size()!=0){
            int t=q.back();q.pop_back();
            ct++;
            for(int i=0;i<p[t].size();i++){
                int x=p[t][i];
                if(--in[x]==0){
                    q.push_back(x);
                }
            }
        }
        if(ct!=n){
            cout<<"NO"<<endl;
        }
        else cout<<"YES"<<endl;
    }
    return 0;
}

 

以上是关于HDU3342有向图判圈DFS&&拓扑排序法的主要内容,如果未能解决你的问题,请参考以下文章

HDU-3342-Legal or Not

hdu 3342 Legal or Not (拓扑排序)

有向图的强连通子图&2次DFS

HDU 1269 -- 迷宫城堡有向图求SCC的数目 &amp;&amp; 模板

hdu1501&amp;&amp;poj2192 Zipper(DFS)

hdu-3388 Coprime---容斥定理&&DFS版