HDU3478 【判奇环/二分图的性质】
题意:
给你一幅图,给你一个起点,然后问你存不存在一个时刻,所有点可以在那个时刻到达。
思路:
这幅图首先是联通的;
如果出现奇数环,则满足在某一时刻都可能到达;
然后判断奇数环用二分图性质搞也是神奇...
#include<bits/stdc++.h> using namespace std; #include<bits/stdc++.h> using namespace std; /* 题意: 使某一时刻到达该图任意顶点: 1.图是联通的, 2.无向图的每一个顶点必须保证能够在奇时刻或偶时刻可以进行访问. (二部图的顶点两个顶点集合只能在奇或偶时刻对齐进行访问) */ const int N=1e5+10; struct asd{ int to; int next; }; asd q[N*10]; int head[N*10],tol; int n,m,s; int col[N]; int pre[N]; void init() { tol=0; memset(head,-1,sizeof(head)); for(int i=0;i<n;i++) pre[i]=i; } void add(int u,int v) { q[tol].to=v; q[tol].next=head[u]; head[u]=tol++; } int Find(int x) { int r=x; while(pre[r]!=r) r=pre[r]; int i=x,j; while(pre[i]!=r) { j=pre[i]; pre[i]=r; i=j; } return r; } void Merge(int a,int b) { int aa=Find(a); int bb=Find(b); if(aa!=bb) pre[aa]=bb; } bool Judge(int s) { queue<int>que; col[s]=0; que.push(s); while(!que.empty()) { int u=que.front();que.pop(); for(int i=head[u];i!=-1;i=q[i].next) { int v=q[i].to; if(col[v]==-1) { col[v]=1-col[u]; que.push(v); } else if(col[v]==col[u]) return false; } } return true; } int main() { int T,cas=1; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&s); init(); int u,v; while(m--) { scanf("%d%d",&u,&v); add(u,v); add(v,u); Merge(u,v); } printf("Case %d: ",cas++); int flag=0; for(int i=0;i<n;i++) if(pre[i]==i) flag++; if(flag!=1) { puts("NO"); continue; } memset(col,-1,sizeof(col)); if(Judge(s)) puts("NO"); else puts("YES"); } return 0; }