HDU-3478 Catch(二分图染色+并查集)

来源:互联网 发布:qq空间病毒式营销源码 编辑:程序博客网 时间:2024/06/05 14:26

题意:

给一个无向图和小偷所在的起点,小偷每秒可以向相连的点出发,警察想知道会不会存在一个时间点小偷出现在每个点都有可能。

思路:

画几个图可以发现,图不连通的时候,必定是NO。如果图连通,会发现小偷的移动就是二分图的A部和B部在交替,而如果图不是一个二分图,那么小偷就能通过奇数环(二分图的环都是偶环),让两部的点混合导致可以同时出现。即当图不是二分图且是连通图时YES,否则NO。特判n==1时YES(没啥用,数据水)。

代码:

#include <bits/stdc++.h>using namespace std;const int maxn = 1e5+5;vector<int> G[maxn];int col[maxn];int t, n, m, s;int f[maxn];int getF(int x){return x==f[x]? x: f[x]=getF(f[x]);}bool dfs(int u, int fa, int key){for(int i = 0; i < G[u].size(); ++i){int v = G[u][i];if(v == fa) continue;if(col[v] == key) return false;if(col[v] == (key^1)) continue;col[v] = key^1;if(!dfs(v, u, key^1)) return false;}return true;}int main(){scanf("%d", &t);for(int _ = 1; _ <= t; ++_){scanf("%d %d %d", &n, &m, &s);memset(col, -1, sizeof col);for(int i = 0; i < n; ++i)G[i].clear(), f[i] = i;for(int i = 1; i <= m; ++i){int u, v;scanf("%d %d", &u, &v);G[u].push_back(v);G[v].push_back(u);f[getF(u)] = getF(v);}printf("Case %d: ", _);bool flag = false;for(int i = 1; i < n; ++i)if(getF(f[i]) != getF(f[0])) flag = true;col[s] = 0;if(!flag) flag = dfs(s, -1, 0);if(!flag || n == 1) puts("YES");else puts("NO");}return 0;}


继续加油~

阅读全文
1 0
原创粉丝点击