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 1269 -- 迷宫城堡有向图求SCC的数目 && 模板