1. 程式人生 > >LOJ-10091(強連通分量)

LOJ-10091(強連通分量)

open dde 答案 強連通 要求 ref iostream 多少 ()

題目鏈接:傳送門

思路:

多少頭牛收到所有牛頭牛的喜歡,喜歡具有傳遞性,所以將互相喜歡的牛視為一個點,就是有向圖的

縮點,收到所有牛的喜歡要求這個“點”沒有出度,所以縮點之後統計所有沒有出度的點就是結果,如果有多頭牛沒有出度,

就說明圖不連通,答案為0。

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 500500;
int num[maxn],low[maxn],vis[maxn],head[maxn],ver[maxn],next[maxn],tot;
int st[maxn],out[maxn],fa[maxn],top,tim,col; int MIN(int x,int y) { return x<y?x:y; } int MAX(int x,int y) { return x>y?x:y; } void Init() { memset(vis,0,sizeof(vis)); memset(low,0,sizeof(low)); memset(num,0,sizeof(num)); memset(head,0,sizeof(head)); memset(ver,0,sizeof
(ver)); memset(next,0,sizeof(next)); memset(st,0,sizeof(st)); memset(out,0,sizeof(out)); memset(fa,0,sizeof(fa)); top=0;tim=0;tot=0;col=0; } void addedge(int u,int v) { ver[++tot]=v;next[tot]=head[u];head[u]=tot; } void Tarjan(int u) //強連通模板 { low[u]=num[u]=++tim; vis[u]=1; st[
++top]=u; for(int i=head[u];i;i=next[i]){ int v=ver[i]; if(!vis[v]){ Tarjan(v); low[u]=MIN(low[u],low[v]); } else if(!fa[v]) low[u]=MIN(low[u],num[v]); } if(low[u]==num[u]){ fa[u]=++col; while(st[top]!=u){ fa[st[top]]=col; top--; } top--; } } int main(void) { int n,m,i,j,x,y; while(~scanf("%d%d",&n,&m)){ Init(); for(i=1;i<=m;i++){ scanf("%d%d",&x,&y); addedge(x,y); } for(i=1;i<=n;i++) if(!vis[i]) Tarjan(i); for(i=1;i<=n;i++){ for(j=head[i];j;j=next[j]){ if(fa[i]!=fa[ver[j]]) out[fa[i]]++; //統計縮點後每個點的出度 } } x=0; int cnt=0,sum=0; for(i=1;i<=col;i++) if(out[i]==0) cnt++,x=i; if(cnt==1){ //當且僅當只有一個“點”時才有結果 for(i=1;i<=n;i++) //統計這個縮點中的點數 if(fa[i]==x) sum++; printf("%d\n",sum); } else printf("0\n"); } return 0; }
View Code

LOJ-10091(強連通分量)