题目链接:http://codeforces.com/gym/100187/problem/J
题目链接:问通过洗牌器,能否将编号为x的牌子转移到第一个位置?
根据 洗牌器,我们可以知道原本在第i位置的牌可以转移到第j个位置,且这种转移是单向的。如果要把在某个位置的牌转移到第一个位置,那么必须至少存在一条转换路径,其起点为这张牌的位置,起终点为第一个位置。所以就很自然想到建图,然后用dfs跑一遍。
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #include<string> 11 #include<set> 12 //#define LOCAL 13 using namespace std; 14 #define pb push_back 15 #define ms(a, b) memset(a,b,sizeof(a)); 16 typedef long long LL; 17 const int inf = 0x3f3f3f3f; 18 const int mod = 1000000007; 19 const int maxn = 10; 20 21 int a[200010]; 22 vector<int>v[200010]; 23 int vis[200010]; 24 25 int dfs(int u) 26 { 27 if(u==1) 28 return 1; 29 30 vis[u] = 1; 31 int num = v[u].size(); 32 for(int i = 0; i<num; i++) 33 { 34 if(!vis[v[u][i]]) 35 { 36 if(dfs(v[u][i])) return 1; 37 } 38 } 39 return 0; 40 } 41 42 int main() 43 { 44 int n,k,x; 45 scanf("%d",&n); 46 for(int i = 1; i<=n; i++) 47 { 48 scanf("%d",&x);//记录编号为x的牌在哪个位置 49 a[x] = i; 50 v[i].clear(); 51 } 52 53 scanf("%d",&k); 54 for(int i = 0; i<k; i++) 55 for(int j = 1; j<=n; j++) 56 { 57 scanf("%d",&x); 58 if(x==j) continue; 59 v[x].pb(j);//单向图 60 } 61 62 scanf("%d",&x); 63 if(dfs(a[x]))//起点为:编号为x的牌所处的位置 64 puts("YES"); 65 else 66 puts("NO"); 67 68 }