二分图的一个重要性质
一个图如果是二分图,那么这个图不存在奇环,反之也成立
模板题目:Catch
题意:一个无向图有\(n\)个节点,\(m\)条边,从编号为\(s\)的点出发,每个单位时间可以从当前点走到一个相邻的点,问存不存在这样一个时刻,从\(s\)出发,可以在这个时刻到达任何一个点。
题解:我们称那个符合要求的时刻为:完美时刻.首先如果这个无向图是不连通,就不存在完美时刻. 当无向图连通的时候,如果该图是二分图,依然不存在完美时刻。因为整个图被分为两半,一半是奇数时刻能到的,另一半是偶数时刻能到的。
综上所述,只有在图连通且非二分图的时候,才能保证有完美时刻存在.我们只需要判断图是否连通且非二分图即可.其中图是否连通可以直接通过从起点S对图节点染色后,看看是否还有未染色的节点来得出.(错误,不可通过二分图递归判断,因为如果颜色冲突了就立即返回,其他点都没有染色). 连通必须通过并查集判断.
AC_Code:
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <vector> 5 using namespace std; 6 typedef long long ll; 7 #define endl '\n' 8 const int mod=998244353; 9 const int maxn=1e5+10; 10 const int maxm=5e5+10; 11 12 int n,m,s; 13 vector<int>G[maxn]; 14 int color[maxn]; 15 int fa[maxn]; 16 bool flag; 17 18 int find_fa(int i){ 19 if( fa[i]==i ) return i; 20 return fa[i]=find_fa(fa[i]); 21 } 22 23 void init(){ 24 for(int i=0;i<n;i++){ 25 G[i].clear(); 26 fa[i]=i; 27 } 28 memset(color,0,sizeof(color)); 29 flag=true; 30 } 31 32 bool dfs(int u,int c){ 33 color[u]=c; 34 for(size_t i=0;i<G[u].size();i++){ 35 int to=G[u][i]; 36 if( !flag ) return false; 37 else if( !color[to] ){ 38 dfs(to,3-c); 39 }else if( color[to]==c ){ 40 return flag=false; 41 } 42 } 43 return true; 44 } 45 46 int main() 47 { 48 int t,cas=0; scanf("%d",&t); 49 while( t-- ){ 50 scanf("%d%d%d",&n,&m,&s); 51 init(); 52 while( m-- ){ 53 int u,v; scanf("%d%d",&u,&v); 54 G[u].push_back(v); 55 G[v].push_back(u); 56 u=find_fa(u); 57 v=find_fa(v); 58 if( u!=v ) fa[u]=v; 59 } 60 int cnt=0;//连通分量个数 61 for(int i=0;i<n;i++){ 62 if( find_fa(i)==i ) 63 cnt++; 64 } 65 if( cnt>1 ){ 66 printf("Case %d: NO\n",++cas); 67 continue; 68 } 69 if( !dfs(s,1) ) printf("Case %d: YES\n",++cas);//如果不是二分图则存在这么一个时刻 70 else printf("Case %d: NO\n",++cas);//否则不存在 71 } 72 return 0; 73 }
大佬博客:here