题目大意:
约翰的N(2≤N≤10000)只奶牛非常兴奋,因为这是舞会之夜!她们穿上礼服和新鞋子,别上鲜花,她们要表演圆舞。
只有奶牛才能表演这种圆舞.圆舞需要一些绳索和一个圆形的水池.奶牛们围在池边站好,顺时针顺序由1到N编号.每只奶牛都面对水池,这样她就能看到其他的每一只奶牛.为了跳这种圆舞,她们找了M(2≤M≤50000)条绳索.若干只奶牛的蹄上握着绳索的一端,绳索沿顺时针方绕过水池,另一端则捆在另一些奶牛身上.这样,一些奶牛就可以牵引另一些奶牛.有的奶牛可能握有很多绳索,也有的奶牛可能一条绳索都没有握。比如说贝茜,她的圆舞跳得是否成功,可以这样检验:沿着她牵引的绳索,找到她牵引的奶牛,再沿着这只奶牛牵引的绳索,又找到一只被牵引的奶牛,如此下去,若最终能回到原位,则她的圆舞跳得成功,因为这一个环上的奶牛可以逆时针牵引而跳起旋转的圜舞.如果不能回到原位,那她的圆舞是不成功的.
如果两只成功跳圆舞的奶牛有绳索相连,那她们可以同属一个组合.
给出每一条绳索的描述,请找出,成功跳了圆舞的奶牛有多少个组合?
样例输入:
5 4 2 4 3 5 1 2 4 1
样例输出:
1
题解
一句话题意。给定一个有向图,问有多少个大于等于2的强联通分量。多组数据,练习模板清空数组。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 struct node 7 { 8 int next,to; 9 } e[100005]; 10 int head[10005],dfn[10005],low[10005],cnt,time,s[10005]; 11 int vis[10005],ans; 12 inline void insert(int u,int v) 13 { 14 e[++cnt].next=head[u]; 15 head[u]=cnt; 16 e[cnt].to=v; 17 } 18 inline void tarjan(int now) 19 { 20 dfn[now]=low[now]=++time; 21 s[++s[0]]=now;vis[now]=1; 22 for(int i=head[now];i;i=e[i].next) 23 { 24 if(!dfn[e[i].to]) 25 { 26 tarjan(e[i].to); 27 low[now]=min(low[now],low[e[i].to]); 28 } 29 else if(vis[e[i].to]) 30 low[now]=min(low[now],dfn[e[i].to]); 31 } 32 if(low[now]==dfn[now]) 33 { 34 int num=1; 35 vis[now]=0; 36 while(s[s[0]]!=now) 37 { 38 vis[s[s[0]]]=0; 39 num++; 40 s[0]--; 41 } 42 s[0]--; 43 if(num>=2) ans++; 44 } 45 } 46 int main() 47 { 48 int n,m,u,v; 49 while(scanf("%d%d",&n,&m)!=EOF) 50 { 51 memset(dfn,0,sizeof(dfn)); 52 memset(low,0,sizeof(low)); 53 memset(head,0,sizeof(head)); 54 memset(s,0,sizeof(s)); 55 cnt=0,time=0,ans=0; 56 for(int i=1;i<=m;i++) 57 { 58 scanf("%d%d",&u,&v); 59 insert(u,v); 60 } 61 for(int i=1;i<=n;i++) 62 if(!dfn[i]) tarjan(i); 63 printf("%d\n",ans); 64 } 65 return 0; 66 }