HDU 3560--Graph’s Cycle Component【并查集(判环)】

来源:互联网 发布:java定时任务管理模块 编辑:程序博客网 时间:2024/06/01 09:24


Graph’s Cycle Component

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 2147    Accepted Submission(s): 784


Problem Description
In graph theory, a cycle graph is an undirected graph that consists of a single cycle, or in other words, some number of vertices connected in a closed chain.
Now, you are given a graph where some vertices are connected to be components, can you figure out how many components are there in the graph and how many of those components are cycle graphs.
Two vertices belong to a same component if and only if those two vertices connect each other directly or indirectly.
 

Input
The input consists of multiply test cases.
The first line of each test case contains two integer, n (0 < n < 100000), m (0 <= m <= 300000), which are the number of vertices and the number of edges.
The next m lines, each line consists of two integers, u, v, which means there is an edge between u and v.
You can assume that there is no multiply edges and no loops.
The last test case is followed by two zeros, which means the end of input.
 

Output
For each test case, output the number of all the components and the number of components which are cycle graphs.
 

Sample Input
8 90 11 32 30 24 55 76 74 64 72 10 10 0
 

Sample Output
2 11 0
 

题目大意:给定一个n表示图的顶点个数,一个m表示图的边的个数,然后是m对数x y,表示x和y节点之间有一条边。求该图有几个部分组成,这些组成部分中又有几个是环。

思想:并查集判断部分的个数,用点的度来判断是否是环,点构成环的充要条件是该环中每个点的度皆为2;

 1、初始化每个点的度为0,每个点所属集合(根节点)为其自身,标记值flag=1;

 2、对于每组输入数据,相应的点的度加1;查找两个点的根节点,如果不相等则合并之;

 3、遍历每个点,如果其度不为2,找到其根节点,将其根节点标记flag=0,表示该集合不可能为环;

 4、遍历查找答案,看per[i]与i是否相等,若相等,则部分数加1,再判断其标记值是否为1,若是则环数加1;


#include<stdio.h>#define maxn 1000100int per[maxn],num[maxn],flag[maxn];int find(int x){//不能压缩路径,不然会超时    int p=per[x];    while(x!=per[x]) x=per[x];    per[p]=x;    return x;}int main(){    int n,m,x,y,i;    while(scanf("%d%d",&n,&m),(n+m)){        for(i=0;i<n;i++) {            per[i]=i; num[i]=0; flag[i]=1;//用num记录每个点的度,        }        while(m--){            scanf("%d%d",&x,&y);            num[x]++;            num[y]++;            int fx=find(x),fy=find(y);            if(fx!=fy) per[fx]=fy;        }        int u=0,v=0;        for(i=0;i<n;i++)            if(num[i]!=2)                flag[find(i)]=0;        for(i=0;i<n;i++){            if(per[i]==i){                u++;                if(flag[i]==1) v++;            }        }        printf("%d %d\n",u,v);    }    return 0;}


0 0
原创粉丝点击