【二部图的判定】Catch
Catch
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1397 Accepted Submission(s): 687
Problem Description
A thief is running away!
We can consider the city where he locates as an undirected graph in which nodes stand for crosses and edges stand for streets. The crosses are labeled from 0 to N–1.
The tricky thief starts his escaping from cross S. Each moment he moves to an adjacent cross. More exactly, assume he is at cross u at the moment t. He may appear at cross v at moment t + 1 if and only if there is a street between cross u and cross v. Notice that he may not stay at the same cross in two consecutive moment.
The cops want to know if there’s some moment at which it’s possible for the thief to appear at any cross in the city.
We can consider the city where he locates as an undirected graph in which nodes stand for crosses and edges stand for streets. The crosses are labeled from 0 to N–1.
The tricky thief starts his escaping from cross S. Each moment he moves to an adjacent cross. More exactly, assume he is at cross u at the moment t. He may appear at cross v at moment t + 1 if and only if there is a street between cross u and cross v. Notice that he may not stay at the same cross in two consecutive moment.
The cops want to know if there’s some moment at which it’s possible for the thief to appear at any cross in the city.
Input
The input contains multiple test cases:
In the first line of the input there’s an integer T which is the number of test cases. Then the description of T test cases will be given.
For any test case, the first line contains three integers N (≤ 100 000), M (≤ 500 000), and S. N is the number of crosses. M is the number of streets and S is the index of the cross where the thief starts his escaping.
For the next M lines, there will be 2 integers u and v in each line (0 ≤ u, v < N). It means there’s an undirected street between cross u and cross v.
In the first line of the input there’s an integer T which is the number of test cases. Then the description of T test cases will be given.
For any test case, the first line contains three integers N (≤ 100 000), M (≤ 500 000), and S. N is the number of crosses. M is the number of streets and S is the index of the cross where the thief starts his escaping.
For the next M lines, there will be 2 integers u and v in each line (0 ≤ u, v < N). It means there’s an undirected street between cross u and cross v.
Output
For each test case, output one line to tell if there’s a moment that it’s possible for the thief to appear at any cross. Look at the sample output for output format.
Sample Input
2
3 3 0
0 1
0 2
1 2
2 1 0
0 1
3 3 0
0 1
0 2
1 2
2 1 0
0 1
Sample Output
Case 1: YES
Case 2: NO
题目大意:
有一个人,从S点出发,他可能朝任意一条路走到另外一点,走每一条路都需要花费1单位的时间,每一条路可以重复走,问,他是否能够在奇数时刻以及偶数时刻出现在同一点,而且,每个点都能够满足这一条件的话,则输出YES,否则输出NO。
解法:
在做这道题目之前,需要了解一下二部图的一些性质,如果一幅图为二部图的充分必要条件是,这幅联通图的任意一个环都为偶数环。
相对于,题目所要求的,要使得他能够在偶数时刻以及奇数时刻出现在同一点上,需要的是这个环必须是奇数环,因为奇数环的话,才能使得,在偶数或者奇数时刻出现在环上任意的同一点上,而且,只要联通图存在一个奇数环的话,也就能保存图上的任意一点都能过在偶数时刻以及奇数时刻出现。因为我们刚开始出发的时间为0,既为偶数时刻,连接它的下一点就是奇数时刻,你是从S点出发的,如果形成奇数环的话,也就是说明S点也能在奇数时刻到达,他的下一点也就能够变成偶数时刻了的,也就是说S可以变成偶数时刻出发以及奇数时刻出发,对于联通图上任意一点同样能够变成奇数时刻以及偶数时刻了的、如果他,不存在这一种情况的话,则说明这幅联通图上的环都为偶数环,也就是说这幅图是二部图,总而言之,其实就是让我们判断这幅图是不是二部图而已,是的话输出NO,不是的话输出YES即可。
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <math.h> 5 #define MAX 500010 6 using namespace std; 7 struct edge{int to,next;}edge[MAX*2]; 8 int Vis[MAX];/*点标记*/ 9 int Sign[MAX];/*奇偶染色*/ 10 int First[MAX]; 11 int Top;/*边的编号 及 判断标志*/ 12 void Add_E(int x,int y) 13 { 14 edge[Top].to=y; 15 edge[Top].next=First[x]; 16 First[x]=Top++; 17 } 18 void Cread(int N) 19 { 20 for(int i=0;i<=N;i++){ 21 First[i]=Sign[i]=0; 22 Vis[i]=1; 23 }Top=1; 24 } 25 /*void DFS(int n)//深搜+染色 26 { 27 if(Top)return; 28 for(int i=First[n];i;i=edge[i].next){ 29 int TMD=edge[i].to; 30 if(Vis[TMD]){ 31 Vis[TMD]=0; 32 Sign[TMD]=!Sign[n]; 33 DFS(TMD); 34 } 35 else if(Sign[TMD]==Sign[n]) {Top=1;return;} 36 } 37 }*/ 38 39 void BFS(int n)/*广搜+染色*/ 40 { 41 int Q[MAX]; 42 int S=0,E=1,k; 43 Q[S]=n; 44 while(S<E){ 45 k=Q[S++]; 46 for(int i=First[k];i;i=edge[i].next){ 47 int TMD=edge[i].to; 48 if(Vis[TMD]){ 49 Vis[TMD]=0; 50 Sign[TMD]=!Sign[k]; 51 Q[E++]=TMD; 52 } 53 else if(Sign[TMD]==Sign[k]) {Top=1;return;} 54 } 55 } 56 } 57 58 int main() 59 { 60 int k,n,m,i,j,s,T,t=1; 61 scanf("%d",&T); 62 while(T--) 63 { 64 scanf("%d%d%d",&n,&m,&s); 65 Cread(n); 66 for(i=0;i<m;i++){ 67 int a,b;/*这里输入的编号是0~N-1*/ 68 scanf("%d%d",&a,&b);a++,b++; 69 Add_E(a,b);Add_E(b,a); 70 } 71 Top=0;Sign[s+1]=0;Vis[s+1]=0; 72 BFS(s+1); 73 printf("Case %d: ",t++); 74 if(Top)printf("YES\n"); 75 else printf("NO\n"); 76 } 77 return 0; 78 }
转载请备注:
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************