题目大意:
约翰的N(2≤N≤10000)只奶牛非常兴奋,因为这是舞会之夜!她们穿上礼服和新鞋子,别上鲜花,她们要表演圆舞.
只有奶牛才能表演这种圆舞.圆舞需要一些绳索和一个圆形的水池.奶牛们围在池边站好,顺时针顺序由1到N编号.每只奶牛都面对水池,这样她就能看到其他的每一只奶牛.为了跳这种圆舞,她们找了M(2≤M≤50000)条绳索.若干只奶牛的蹄上握着绳索的一端,绳索沿顺时针方绕过水池,另一端则捆在另一些奶牛身上.这样,一些奶牛就可以牵引另一些奶牛.有的奶牛可能握有很多绳索,也有的奶牛可能一条绳索都没有握。比如说贝茜,她的圆舞跳得是否成功,可以这样检验:沿着她牵引的绳索,找到她牵引的奶牛,再沿着这只奶牛牵引的绳索,又找到一只被牵引的奶牛,如此下去,若最终能回到原位,则她的圆舞跳得成功,因为这一个环上的奶牛可以逆时针牵引而跳起旋转的圜舞.如果不能回到原位,那她的圆舞是不成功的.
如果两只成功跳圆舞的奶牛有绳索相连,那她们可以同属一个组合.
给出每一条绳索的描述,请找出,成功跳了圆舞的奶牛有多少个组合?
题目分析: 求的是有多个大于等于2的强联通分量;
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> #include <vector> usingnamespace std; #define INF 0x7ffffff #define maxn 10005 typedef longlong LL; #define Min(a,b) (a<b?a:b) #define MOD 1000000007 int m, n, Time, top, ans; int Stack[maxn], dfn[maxn], low[maxn]; bool InStack[maxn]; vector<vector<int> > G; void init() { memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); ans = Time = top = 0; G.clear(); G.resize(n+2); } void Tarjan(int u) { dfn[u] = low[u] = ++Time; Stack[top++] = u; InStack[u] = true; int len = G[u].size(), v, k = 0; for(int i=0; i<len; i++) { v = G[u][i]; if( !low[v] ) { Tarjan(v); low[u] = min(low[u], low[v]); } elseif( InStack[v] ) low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) { do { v = Stack[--top]; k ++; InStack[u] = false; }while(u != v); if(k >= 2) ans ++; } } void solve() { for(int i=1; i<=n; i++) { if(!low[i]) Tarjan(i); } printf("%d\n", ans); } int main() { while(scanf("%d %d",&n, &m) != EOF) { init(); while(m --) { int a, b; scanf("%d %d",&a, &b); G[a].push_back(b); } solve(); } return0; }
时间: 2024-10-12 17:02:06