Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛 A 认为牛 B受欢迎。这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
Input
第1行两个整数N,M;
接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1
Hint
10%的数据N<=20,M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
Solution
首先,如果数据很小的话可以用传递闭包对吧,但是N到了1e5就显然不行了。
显然如果在一个环里的各个点的传递是互达的,由此我们可以扩展到一个强连通分量也是这样。
于是我们就可以想到tarjan缩点。
缩完点后怎么办呢?愚蠢的我想到一个点的入度=点数-1就对答案产生贡献,显然是不对的(如 3->2->1)。
于是我第一遍只有70分,(这样都有70分可能是数据太水了)。
脑子不好使的我冒着被卡的风险在缩完点后使用传递闭包(不要问我为什么我这么喜欢传递闭包),居然过了!(可能是数据太水了)
然后我便看正解,发现果然还是大佬们聪明一点。
对于缩完点后的点x
i)如果出度!=0,那么肯定有没指向自己的点,(如果有指出去后又指回来肯定在连通分量内)
ii)如果出度==0,似乎这个连通分量内的点就是答案,但是如果有多个出度为0的点,就说明还有多个独立的区域,那也不行。
所以出度==0的点有且只有一个的时候即为答案
Code (传递闭包版)
1 #include<set> 2 #include<stack> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define RG register int 8 #define rep(i,a,b) for(RG i=a;i<=b;i++) 9 #define per(i,a,b) for(RG i=a;i>=b;i--) 10 #define inf (1<<30) 11 #define maxn 10005 12 #define maxm 500005 13 #define add(x,y) e[++cnt].u=u,e[cnt].v=v,e[cnt].next=head[u],head[u]=cnt 14 using namespace std; 15 stack<int> stk; 16 set<int> st[maxn]; 17 int n,m,cnt,id,sid,ans; 18 int head[maxn],scc[maxn],dfn[maxn],low[maxn],vis[maxn],ind[maxn],sz[maxn],oud[maxn]; 19 int gra[1000][1000]; 20 struct E{ 21 int u,v,next; 22 }e[maxm]; 23 inline int read() 24 { 25 int x=0,f=1;char c=getchar(); 26 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 27 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 28 return x*f; 29 } 30 31 void tarjan(int u,int fa) 32 { 33 low[u]=dfn[u]=++id; 34 stk.push(u);vis[u]=1; 35 for(int i=head[u];i;i=e[i].next) 36 { 37 int v=e[i].v; 38 if(!dfn[v]) 39 { 40 tarjan(v,u);low[u]=min(low[u],low[v]); 41 } 42 else if(vis[v]) low[u]=min(low[u],dfn[v]); 43 } 44 if(low[u]==dfn[u]) 45 { 46 ++sid;int x; 47 do{ 48 x=stk.top(),stk.pop(); 49 vis[x]=0,scc[x]=sid,sz[sid]++; 50 }while(x!=u); 51 } 52 } 53 54 55 56 int main() 57 { 58 n=read(),m=read(); 59 RG u,v;rep(i,1,m) u=read(),v=read(),add(u,v); 60 rep(i,1,n) if(!scc[i]) tarjan(i,0); 61 rep(i,1,cnt) 62 { 63 int x=scc[e[i].u],y=scc[e[i].v]; 64 if(x!=y) 65 gra[x][y]=1; 66 } 67 rep(k,1,sid) 68 rep(i,1,sid) 69 rep(j,1,sid) 70 if(gra[i][k]&&gra[k][j])gra[i][j]=1; 71 rep(i,1,sid) 72 { 73 int flg=0; 74 rep(j,1,sid) 75 if(i!=j&&!gra[j][i]) flg=1; 76 if(!flg) ans+=sz[i]; 77 } 78 cout<<ans; 79 return 0; 80 }
1 #include<set> 2 #include<stack> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define RG register int 8 #define rep(i,a,b) for(RG i=a;i<=b;i++) 9 #define per(i,a,b) for(RG i=a;i>=b;i--) 10 #define inf (1<<30) 11 #define maxn 10005 12 #define maxm 500005 13 #define add(x,y) e[++cnt].u=u,e[cnt].v=v,e[cnt].next=head[u],head[u]=cnt 14 using namespace std; 15 stack<int> stk; 16 set<int> st[maxn]; 17 int n,m,cnt,ccnt,id,sid,ans; 18 int head[maxn],hh[maxn],scc[maxn],dfn[maxn],low[maxn],vis[maxn],ind[maxn],sz[maxn],oud[maxn]; 19 int gra[1000][1000]; 20 struct E{ 21 int u,v,next; 22 }e[maxm]; 23 struct EE{ 24 int v,next; 25 }edge[maxm]; 26 inline int read() 27 { 28 int x=0,f=1;char c=getchar(); 29 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 30 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 31 return x*f; 32 } 33 34 void tarjan(int u,int fa) 35 { 36 low[u]=dfn[u]=++id; 37 stk.push(u);vis[u]=1; 38 for(int i=head[u];i;i=e[i].next) 39 { 40 int v=e[i].v; 41 if(!dfn[v]) 42 { 43 tarjan(v,u);low[u]=min(low[u],low[v]); 44 } 45 else if(vis[v]) low[u]=min(low[u],dfn[v]); 46 } 47 if(low[u]==dfn[u]) 48 { 49 ++sid;int x; 50 do{ 51 x=stk.top(),stk.pop(); 52 vis[x]=0,scc[x]=sid,sz[sid]++; 53 }while(x!=u); 54 } 55 } 56 57 58 59 int main() 60 { 61 n=read(),m=read(); 62 RG u,v;rep(i,1,m) u=read(),v=read(),add(u,v); 63 rep(i,1,n) if(!scc[i]) tarjan(i,0); 64 rep(i,1,cnt) 65 { 66 int x=scc[e[i].u],y=scc[e[i].v]; 67 if(x!=y) 68 gra[x][y]=1; 69 } 70 rep(k,1,sid) 71 rep(i,1,sid) 72 rep(j,1,sid) 73 if(gra[i][k]&&gra[k][j])gra[i][j]=1; 74 rep(i,1,sid) 75 { 76 int flg=0; 77 rep(j,1,sid) 78 if(i!=j&&!gra[j][i]) flg=1; 79 if(!flg) ans+=sz[i]; 80 } 81 cout<<ans; 82 return 0;