传送门
这道题可以用暴力水过,不用tarjan
思路:将奶牛看成节点,反向建边,对于一只奶牛,跑一边暴力dfs,判断能不能到达其他所有奶牛,然后加一些小小的剪枝就可以过了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #define MAXN 10005 using namespace std; int vis[MAXN]; int is_all[MAXN]; int sz[MAXN]; int haveans; vector<int>G[MAXN]; void dfs(int u){ if (haveans==1){ return ; } for (register int i=0;i<sz[u];++i){ if (!vis[G[u][i]]){ vis[G[u][i]]=true; if (is_all[G[u][i]]==1){ haveans=is_all[G[u][i]]; return ; } dfs(G[u][i]); } } } int main(){ int n,m; scanf("%d%d",&n,&m); for (register int i=0;i<m;++i){ int u,v; scanf("%d%d",&u,&v); vis[u]=true,vis[v]=true; G[v].push_back(u); } bool flag=false; for (register int i=1;i<=n;++i){ if (vis[i]==0){ flag=true; break; } } if (flag==true){ printf("0\n"); return 0; } for (register int i=1;i<=n;++i){ sort(G[i].begin(),G[i].end()); sz[i]=unique(G[i].begin(),G[i].end())-G[i].begin(); } int sum=0; memset(is_all,-1,sizeof(is_all)); for (register int i=1;i<=n;++i){ if (is_all[i]==0){ continue; } haveans=-1; memset(vis,0,sizeof(vis)); vis[i]=true; dfs(i); if (haveans==1){ is_all[i]=1; sum++; } else if (haveans==-1){ bool flag=false; for (register int j=1;j<=n;++j){ if (vis[j]==0){ flag=true; break; } } if (flag==false){ is_all[i]=1; sum++; } else { for (register int j=1;j<=n;++j){ if (vis[j]) is_all[j]=0; } } } } printf("%d\n",sum); }
|
然后就可以水过了,膜拜各个大佬的tarjan