图论- hdu5222 Exploration

来源:互联网 发布:apache index.html 编辑:程序博客网 时间:2024/06/18 13:31

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5222


题意:

给一个图,图中有若干有向边,若干无向边,有重边,无自环,问图中是否存在环


思路:

分类考虑

先判断无向边中是否存在环,

若不存在,则仅由 点 与 无向边 组成的图,为若干独立的连通子图,且均为生成树;

再考虑有向边,

若存在一有向边弧头和弧尾属于同一连通子图,则必然该子图内存在存在环

若不存在,则将每个连通子图抽象为一个节点,判断有向图中是否存在环

判断无向图中的环可以用并查集,有向图中的环用拓扑排序即可


代码:

#include<iostream>#include<vector>#include<stdio.h>#include<queue>#include<string.h>#include<map>using namespace std;const int MAXSIZE = 1000005;map<int,int> node_arr;vector<int> adjlist[MAXSIZE];int s_set[MAXSIZE];int s_rank[MAXSIZE];int num[MAXSIZE];int s_find(int x){int k = x, t;while (k != s_set[k])k = s_set[k];while (x != k){t = s_set[x];s_set[x] = k;x = t;}return x;}void s_union(int x, int y){x = s_find(x);y = s_find(y);if (x == y) return;if (s_rank[x] >= s_rank[y]){s_set[y] = x;if (s_rank[x] == s_rank[y]) s_rank[x]++;num[x] += num[y];}else{s_set[x] = y;num[y] += num[x];}return;}int main(){    int total;    cin>>total;    while (total--){        int n,m1,m2;        cin>>n>>m1>>m2;        for (int i=1;i<=n;++i){            adjlist[i].clear();        }        for (int i = 0; i <= n; ++i){            s_set[i] = i;            s_rank[i] = num[i] = 1;        }        bool isLoop = false;        for (int i=1;i<=m1;++i){            int a,b;            scanf("%d %d",&a,&b);            if (s_find(a) ==s_find(b)){                isLoop=true;            }            else s_union(a,b);        }        node_arr.clear();        for (int i=1;i<=m2;++i){            int a,b;            scanf("%d %d",&a,&b);            if (s_find(a) == s_find(b)) isLoop=true;            adjlist[s_find(a)].push_back(s_find(b));            node_arr[s_find(a)];            node_arr[s_find(b)]++;        }        //in        if (isLoop) cout<<"YES"<<endl;        else {//            for (int i=1;i<=n;++i)//                cout<<"i:"<<i<<" "<<s_find(i)<<endl;            queue<int> q;            for (map<int,int>::iterator it=node_arr.begin();it!=node_arr.end(); ++it){                //cout<<it->first<<" "<<it->second<<endl;                if (it->second==0){                    q.push(it->first);                    it->second=-1;                }            }            while (!q.empty()){                int t=q.front();//               cout<<"q:"<<t<<endl;                q.pop();                for (int i=0;i<adjlist[t].size();++i){                    if ((--node_arr[adjlist[t][i]])==0){                        q.push(adjlist[t][i]);                        node_arr[adjlist[t][i]]=-1;                    }                }            }            for (map<int,int>::iterator it=node_arr.begin();it!=node_arr.end();++it){//                cout<<it->first<<" "<<it->second<<endl;                if (it->second!=-1){                    isLoop=true;                    break;                }            }            if (isLoop) cout<<"YES"<<endl;            else cout<<"NO"<<endl;        }    }    return 0;}



0 0
原创粉丝点击