Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 28430 | Accepted: 11511 |
Description
Input
Output
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
Hint
有n只牛,牛A认为牛B很牛,牛B认为牛C很牛。给你M个关系(谁认为谁牛),求大家都认为它很牛的牛有几只。PS:如果牛A认为牛B很牛,牛B认为牛C很牛。那么我们就认为牛A认为牛C很牛。
先用tarjan或Kosaraju跑一遍,缩点,用f[i]表示i结点所在的强连通分量。然后处理每一条边,如果这条边是从一个强连通分量连向另一个强连通分量,则前者的出度增加一。如果发现最后只有一个强连通分量的出度为零,则答案就是这个强连通分量的点的个数。若有多个或没有一个强连通分量的出度为0,则输出0(为什么? -----想想就明白了)。然后要注意只有一个点、零条边的特殊情况,这种情况下答案应该是0。
下面的两个程序一个是用tarjan预处理的,一个是用Kosaraju预处理的。
//tarjan #include<cstdio> #include<cstring> #include<algorithm> #define maxn 11000 #define maxm 51000 #define init(a,x) memset(a,x,sizeof(a)) using namespace std; int N, M, head[maxn], next[maxm], to[maxm], f[maxn], vis[maxn], dfn[maxn], low[maxn], cd[maxn], countt[maxn], time, s[maxn], top, tot; int tarjan(const int x) { int p, t; dfn[x]=low[x]=++time; vis[x]=1; s[++top]=x; for(p=head[x];p;p=next[p]) { if(vis[to[p]]==0)tarjan(to[p]); if(vis[to[p]]==1)low[x]=min(low[x],low[to[p]]); } if(dfn[x]==low[x]) { for(;s[top]^x;top--) { f[ s[top] ]=x; countt[x]++; vis[ s[top] ]=2; } top--; f[x]=x;countt[x]++; vis[x]=2; } } int main() { int i, p, a, b, cnt, ans; while(scanf("%d%d",&N,&M)!=EOF) { init(head,0);init(next,0);tot=0; init(vis,0);time=0;init(cd,0);init(countt,0); for(i=1;i<=M;i++) { scanf("%d%d",&a,&b); to[++tot]=b;next[tot]=head[a];head[a]=tot; } for(i=1;i<=N;i++)if(vis[i]==0)tarjan(i); for(i=1;i<=N;i++) for(p=head[i];p;p=next[p]) if(f[to[p]]!=f[i])cd[f[i]]++; cnt=0;ans=0; for(i=1;i<=N;i++) if(f[i]==i && cd[i]==0) { cnt++; if(ans==0)ans=countt[i]; } if(N==1&&M==0)cnt=0; if(cnt!=1)printf("0\n"); else printf("%d\n",ans); } return 0; }
//Kosaraju #include<cstdio> #include<cstring> #define maxn 11000 #define maxm 110000 #define init(a,x) memset(a,x,sizeof(a)) using namespace std; int head[maxn], next[maxm], to[maxm], tot, cnt, f[maxn], N, M, vis[maxn], dfn[maxn], cd[maxn], s[maxn], top, ans, first; void dfs1(const int x) { int p; vis[x]=true; for(p=head[x];p;p=next[p]) if(!vis[to[p]]&&(p&1))dfs1(to[p]); s[++top]=x; } void dfs2(const int x, const int fa) { int p; f[x]=fa; for(p=head[x];p;p=next[p]) if(!f[to[p]]&&(~p&1))dfs2(to[p],fa); } int main() { int i, a, b, p; while(scanf("%d%d",&N,&M)!=EOF) { init(head,0);init(next,0); init(f,0);init(vis,0);init(cd,0); top=tot=cnt=ans=first=0; for(i=1;i<=M;i++) { scanf("%d%d",&a,&b); to[++tot]=b; next[tot]=head[a]; head[a]=tot; to[++tot]=a; next[tot]=head[b]; head[b]=tot; } for(i=1;i<=N;i++) if(!vis[i])dfs1(i); for(;top;top--) if(!f[s[top]])dfs2(s[top],s[top]); for(i=1;i<=N;i++) for(p=head[i];p;p=next[p]) if((p&1)&&f[to[p]]!=f[i])cd[f[i]]++; for(i=1;i<=N;i++) if(cd[i]==0 && f[i]==i) { cnt++; if(first==0)first=i; } if(cnt!=1)printf("0\n"); else if(N==0)printf("0\n"); else { for(i=1;i<=N;i++) if(f[i]==first)ans++; printf("%d\n",ans); } } return 0; }