ZOJ 3811 Untrusted Patrol dfs
Edward is a rich man. He owns a large factory for health drink production. As a matter of course, there is a large warehouse in the factory.
To ensure the safety of drinks, Edward hired a security man to patrol the warehouse. The warehouse has N piles of drinks and M passageways connected them (warehouse is not big enough). When the evening comes, the security man will start to patrol the warehouse following a path to check all piles of drinks.
Unfortunately, Edward is a suspicious man, so he sets sensors on K piles of the drinks. When the security man comes to check the drinks, the sensor will record a message. Because of the memory limit, the sensors can only record for the first time of the security man's visit.
After a peaceful evening, Edward gathered all messages ordered by recording time. He wants to know whether is possible that the security man has checked all piles of drinks. Can you help him?
The security man may start to patrol at any piles of drinks. It is guaranteed that the sensors work properly. However, Edward thinks the security man may not works as expected. For example, he may digs through walls, climb over piles, use some black magic to teleport to anywhere and so on.
Input
There are multiple test cases. The first line of input is an integer T indicates the number of test cases. For each test case:
The first line contains three integers N (1 <= N <= 100000), M (1 <= M <= 200000) and K (1 <= K <= N).
The next line contains K distinct integers indicating the indexes of piles (1-based) that have sensors installed. The following M lines, each line contains two integers Ai and Bi (1 <= Ai, Bi <= N) which indicates a bidirectional passageway connects piles Ai and Bi.
Then, there is an integer L (1 <= L <= K) indicating the number of messages gathered from all sensors. The next line contains L distinct integers. These are the indexes of piles where the messages came from (each is among the K integers above), ordered by recording time.
Output
For each test case, output "Yes" if the security man worked normally and has checked all piles of drinks, or "No" if not.
Sample Input
2 5 5 3 1 2 4 1 2 2 3 3 1 1 4 4 5 3 4 2 1 5 5 3 1 2 4 1 2 2 3 3 1 1 4 4 5 3 4 1 2
Sample Output
No Yes
Author: DAI, Longao
Source: The 2014 ACM-ICPC Asia Mudanjiang Regional First Round
今天做的网络赛,真是简直了,我来总结下这道题目所犯的一系列错误,做这道题目做的好曲折啊。
1.刚开始以为是割点,看了一会,不知道怎么在搜索的过程中判断如果当前节点是割点的话,儿子节点是不是已经访问过了,直到我自己找到了一种割点的反例,就是一种环,哭瞎了。
2.后来的思路和正解有点相近了,就是先把序列的点都标记下来,不能访问。然后,我是这样想的,就是在序列中两两之间找路径,正解也确实是这个思路,但是在确定这个路径的时候,我只想到了这两个点之间做一个dfs,,这样必超时。
3.这样想着想着就到了5点多,最终在网络赛期间也没有做出来。
4.看到了同学是一个一个点的拓展成一个区域,序列中下个点如果拓展的点和这个区域有重合的那么就说明有一条路径,啊啊啊啊啊啊啊,我当时咋没有想到,所以这样来说并查集也是可以做的。
5细节问题:l<k 一定是NO,图不连通的话一定是NO。
代码一 并查集
————————————————————————————————————哭瞎——————————————————————————-——————————————-
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<map> 6 #include<set> 7 #include<cmath> 8 #include<stack> 9 #include<queue> 10 #include<vector> 11 #include<algorithm> 12 #include<sstream> 13 #define inf 0x3f3f3f3f 14 #define PI acos(-1.0) 15 #define eps 1e-6 16 #define LL long long 17 #define MEM(a,b) memset(a,b,sizeof(a)) 18 #define PB push_back 19 #define IN freopen("in.txt","r",stdin); 20 #define OUT freopen("out.txt","w",stdout); 21 #define BUG printf("bug************bug************bug\n"); 22 23 using namespace std; 24 25 const int N=100010; 26 vector <int>G[N]; 27 bool use[N],visit[N]; 28 int q[N],f[N]; 29 bool flag; 30 31 int Find(int u) 32 { 33 if (f[u]!=u) 34 f[u]=Find(f[u]); 35 return f[u]; 36 } 37 38 bool Union(int u,int v) 39 { 40 int fa1=Find(u); 41 int fa2=Find(v); 42 f[fa2]=fa1; 43 return fa1==fa2; 44 } 45 46 void dfs(int u) 47 { 48 for (int i=0;i<G[u].size();i++){ 49 int v=G[u][i]; 50 if (use[v]){ 51 if (!Union(u,v)) 52 dfs(v); 53 } 54 } 55 } 56 57 int main() 58 { 59 int T,n,m,k,u,v,l,fa1,fa2; 60 bool ans; 61 scanf("%d",&T); 62 while (T--){ 63 MEM(use,true); 64 scanf("%d%d%d",&n,&m,&k); 65 for (int i=1;i<=n;i++){ 66 G[i].clear(); 67 f[i]=i; 68 } 69 for (int i=1;i<=k;i++){ 70 scanf("%d",&v); 71 use[v]=false; 72 } 73 for (int i=1;i<=m;i++){ 74 scanf("%d%d",&u,&v); 75 G[u].push_back(v); 76 G[v].push_back(u); 77 } 78 scanf("%d",&l); 79 for (int i=1;i<=l;i++) 80 scanf("%d",&q[i]); 81 if (l<k){ 82 printf("No\n"); 83 } 84 else{ 85 dfs(q[1]); 86 use[q[1]]=true; 87 ans=true; 88 for (int i=2;i<=l;i++){ 89 dfs(q[i]); 90 use[q[i]]=true; 91 fa1=Find(q[i-1]); 92 fa2=Find(q[i]); 93 if (fa1!=fa2){ 94 ans=false; 95 break; 96 } 97 } 98 for (int i=1;i<=n;i++) 99 Find(i); 100 for (int i=2;i<=n;i++) 101 if (f[i]!=f[1]) 102 ans=false; 103 if (ans) 104 printf("Yes\n"); 105 else 106 printf("No\n"); 107 } 108 } 109 return 0; 110 }
代码二 类似floodfill
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<set> #include<cmath> #include<stack> #include<queue> #include<vector> #include<algorithm> #include<sstream> #define inf 0x3f3f3f3f #define PI acos(-1.0) #define eps 1e-6 #define LL long long #define MEM(a,b) memset(a,b,sizeof(a)) #define PB push_back #define IN freopen("in.txt","r",stdin); #define OUT freopen("out.txt","w",stdout); #define BUG printf("bug************bug************bug\n"); using namespace std; const int N=100010; vector <int>G[N]; bool use[N],visit[N]; int q[N]; bool flag; void dfs(int u) { for (int i=0;i<G[u].size();i++){ int v=G[u][i]; if (visit[v]){ flag=true; continue; } else{ if (!use[v]) continue; use[v]=false; dfs(v); visit[v]=true; } } } int main() { int T,n,m,k,u,v,l; bool ans; scanf("%d",&T); while (T--){ MEM(use,true); MEM(visit,false); scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=n;i++) G[i].clear(); for (int i=1;i<=k;i++){ scanf("%d",&v); use[v]=false; } for (int i=1;i<=m;i++){ scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } scanf("%d",&l); for (int i=1;i<=l;i++) scanf("%d",&q[i]); if (l<k){ printf("No\n"); } else{ dfs(q[1]); visit[q[1]]=true; ans=true; for (int i=2;i<=l;i++){ flag=false; dfs(q[i]); visit[q[i]]=true; if (!flag){ ans=false; break; } } for (int i=1;i<=n;i++) if (!visit[i]) ans=false; if (ans) printf("Yes\n"); else printf("No\n"); } } return 0; }