[转载]HDU 3478 判断奇环
题意:给定n个点,m条边的无向图(没有重边和子环)。从给定点出发,每个时间走到相邻的点,可以走重复的边,相邻时间不能停留在同一点,判断是否存在某个时间停留在任意的n个点。
分析:
(1)首先,和出发点的位置没有关系。因为可以走重复的边,且时间没有限制大小。
(2)图必须是联通的
(3)
1)图为:2-0-1-3
从0点出发(时间为0),一个时间后到达1或2(时间为1),再一个时间后到达0或3(时间为2)。。。
可以发现,点分为两类,奇数时间到达和偶数时间到达,答案为NO
2)图为:2-0-1-2(奇环)
· 此图中的点,即可以在奇数时间到达,又可以在偶数时间到达。则答案为YES。比如都有个偶数的到达时间,在小时间在往返的走重复边后,(不改变奇偶,只改变大小,+2)
3)图为:2-0-1-3-2(偶环)
此图中的点和1)类似,同样分为两类。答案为NO
综上:所有点必须都能在奇数时间和偶数时间到达,则需要图能够改变到达点时间奇偶的结构。
由上可知,图中必须存在奇环。问题变成了,判断图是否存在奇环和是否连通。
1 //#pragma warning (disable: 4786)
2 //#pragma comment (linker, "/STACK:16777216")
3 //HEAD
4 #include <cstdio>
5 #include <ctime>
6 #include <cstdlib>
7 #include <cstring>
8 #include <queue>
9 #include <string>
10 #include <set>
11 #include <stack>
12 #include <map>
13 #include <cmath>
14 #include <vector>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18
19 typedef long long LL;
20 const int INF = 1000000007;
21 const double eps = 1e-10;
22 const int maxn = 100010;
23 const int MOD = 9997;
24
25 int n;
26 int m, st;
27 int tot;
28 vector<int>adj[maxn];
29 int vis[maxn];
30 int fla;
31
32 int dfs(int x, int fa, int val)
33 {
34 if (vis[x] == -1) vis[x] = val;
35 else return vis[x];
36 tot++;
37
38 for (int i = 0; i < adj[x].size(); i++)
39 {
40 int y = adj[x][i];
41 //if (y != fa)
42 //{
43 if (vis[x] == dfs(y, x, vis[x] ^ 1))
44 fla = 1;
45 //}
46 }
47 return vis[x];
48 }
49
50 int main ()
51 {
52 int T;
53 cin >> T;
54 int x, y;
55 int ncase = 1;
56 while (T--)
57 {
58 memset(vis, -1, sizeof(vis));///初始化为-1,染成0和1
59 cin >> n >> m >> st;
60 for (int i = 0; i< n; i++) adj[i].clear();
61 while (m--)
62 {
63 scanf("%d%d", &x,&y);
64 adj[x].push_back(y);
65 adj[y].push_back(x);
66 }
67 fla = 0;///判断是否找到奇环
68 tot = 0;///记录联通的点数
69 dfs(st, -1, 0);
70
71 printf("Case %d: ", ncase++);
72 if (fla && tot == n) puts("YES");
73 else puts("NO");
74 }
75 return 0;
76 }
人生就像心电图,想要一帆风顺,除非game-over