HDU 3478 邻接表 hash表 图论

Catch

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1570    Accepted Submission(s): 753


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.
 

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.

 

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
 

Sample Output
   
   
   
   
Case 1: YES Case 2: NO
Hint
For the first case, just look at the table below. (YES means the thief may appear at the cross at that moment) For the second input, at any moment, there’s at least one cross that the thief can’t reach.

题目大意:

       一个贼要逃跑,每过一天换一个城市,不能在一个城市中停留。问,贼有没有可能同时出现在所有的城市。


遇到的问题和思路:

        刚开始想要100000^2的数组,然后肯定是太大了,memory不够。然后是打算用并查集的方法去做,看看能不能形成环,能形成环就一定能够遍历,但是这个的做法如果遇到了连续输入两次相同的值就行不通了,所以要加一个判断的数组,所以又回到了原来的数组上去了。于是看了一下别人的题解:判断能否在奇数步和偶数步的时候同时到达所有的点。然后就做出来了。


给出代码:

#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> using namespace std; int n, m, s, tmp; int vis[100000 + 10][2]; struct point{ int d, cnt; }; vector <int> mp[100000 + 10]; queue <point> que_a; void solve(){ point start, i_next; start.d = s, start.cnt = 0; que_a.push(start); while (!que_a.empty()){ start = que_a.front(); que_a.pop(); int x = mp[start.d].size(); for (int i = 0; i < x; i++){ i_next.d = mp[start.d][i]; i_next.cnt = start.cnt+ 1; if (vis[i_next.d][i_next.cnt % 2] == 0){ vis[i_next.d][i_next.cnt % 2] = 1; que_a.push(i_next); } } } int ans1 = 0, ans2 = 0; for (int i = 0; i < n; i++){ if (vis[i][0] == 1)ans1++; if (vis[i][1] == 1)ans2++; } if (ans1 == n || ans2 == n) printf("Case %d: YES\n", ++tmp); else printf("Case %d: NO\n", ++tmp); } int main(){ int t; scanf("%d", &t); while (t--){ scanf("%d%d%d", &n, &m, &s); for (int i = 0; i < n; i++){ mp[i].clear(); } memset(vis, 0, sizeof(vis)); for (int i = 0; i < m; i++){ int a, b; scanf("%d%d", &a, &b); mp[a].push_back(b); mp[b].push_back(a); } solve(); } return 0; } //然后另外一种解法,就是奇数环这个特殊的环。如果说循环一次回到起点以后,前一个的值和起点的值一样,那就是判断的终点,说明每一个点无论是奇数步还是偶尔步都可以走到。 //这种解法是看这个人的http://www.myexception.cn/program/1905825.html #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<vector> using namespace std; int n, m, s, tmp; struct edge{ int from, to; int next; }ed[100010]; int step[100010]; int head[100010]; void bfs(){ queue <int> que; que.push(s); int flag = 0; step[s] = 1; while (!que.empty()){ int x = que.front(); que.pop(); for (int i = head[x]; i != -1; i = ed[i].next){ int a = ed[i].to; if (step[a] == -1){ step[a] = !step[x]; que.push(a); } else if (step[a] == step[x]){ flag = 1; } } } if (flag == 1) printf("Case %d: YES\n", ++tmp); else printf("Case %d: NO\n", ++tmp); } int main(){ int t; scanf("%d", &t); while (t--){ int cnt = 0; scanf("%d%d%d", &n, &m, &s); memset(step, -1, sizeof(step)); memset(head, -1, sizeof(head)); for (int i = 0; i < m; i++){ int a, b; scanf("%d%d", &a, &b); ed[cnt].from = a; ed[cnt].to = b; ed[cnt].next = head[a]; head[a] = cnt++; } bfs(); } return 0; } </point></int></cmath></queue></algorithm></cstring></cstdio></int></vector></cstring></queue></algorithm></cstdio>

你可能感兴趣的:(HDU 3478 邻接表 hash表 图论)