题意:给你一张有向图,某人会任意选择起点然后走无穷多步,问是否存在一个点(要求输出)不管他起点在何处怎么走都必经?n<=100005,m<=500005.
标程:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=500005; 4 int cnt,vis[N],n,m,u,v,a[N],tried[N],head[N]; 5 struct node{int to,next;}num[N*2]; 6 void add(int x,int y) 7 {num[++cnt].to=y;num[cnt].next=head[x];head[x]=cnt;} 8 int dfs(int x,int ban) 9 { 10 if (x==ban) return 0; 11 vis[x]=1; 12 for (int i=head[x];i;i=num[i].next) 13 if (!vis[num[i].to]) 14 {if (dfs(num[i].to,ban)) return 1;} 15 else if (vis[num[i].to]==1){ 16 for (int j=1;j<=n;j++) 17 if (vis[j]!=1) tried[j]=1; 18 return 1; 19 } 20 vis[x]=2; 21 return 0; 22 } 23 bool check(int ban) 24 { 25 for (int i=1;i<=n;i++) vis[i]=0; 26 for (int i=1;i<=n;i++) 27 if (!vis[i]) 28 if (dfs(i,ban)) return 0; 29 return 1; 30 } 31 int main() 32 { 33 srand(time(NULL)); 34 scanf("%d%d",&n,&m); 35 for (int i=1;i<=m;i++) scanf("%d%d",&u,&v),add(u,v);//注意单向连边 36 for (int i=1;i<=n;i++) a[i]=i; 37 random_shuffle(a+1,a+n+1); 38 for (int i=1;i<=n;i++) 39 { 40 if ((double)clock()/CLOCKS_PER_SEC>0.95) break; 41 if (!tried[a[i]]) 42 if (check(a[i])) return printf("%d ",a[i]),0; 43 } 44 puts("-1"); 45 return 0; 46 }
易错点:1.注意单向连边。
2.random_shuffle可以有效防卡,要srand。
题解: dfs找环
枚举要选择的点,dfs找是否存在一条带环的不经过该点的路径,如果不存在,那么该点为答案;如果存在,那么该路径之外的点一定不可能是答案,标记掉不找。加上卡时就可以过掉。