1. 程式人生 > >HDU3342有向圖判圈DFS&&拓撲排序法

HDU3342有向圖判圈DFS&&拓撲排序法

ble 成了 target href tar -- targe space 排序

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&&拓撲排序法