Equivalent Sets HDU - 3836 2011多校I tarjan強連通分量
阿新 • • 發佈:2018-06-02
-- urn top define 內部 als ems CA head
題意:
給一些集合 要求證明所有集合是相同的
證明方法是,如果$A∈B$,$B∈A$那麽$A=B$成立
每一次證明可以得出一個$X∈Y$
現在已經證明一些$A∈B$成立
求,最少再證明多少次,就可以完成要求
分析
其實就等價於給一個有向圖,問你再加入多少個邊可以使得圖變為強連通圖
給一個圖論經典結論:
"對於一個有向無環圖(DAG),若想讓它成為強連通圖,至少需要添加$max(a,b)$條邊 $a$為入度為0的點的數量,$b$為出度為0的點的數量"
而對於一個有向圖,其每個強連通分量都互相可達,也就是只要到達任意一個點,即可到達內部所有的點
現在,只要對於強連通分量進行縮點,再新圖中統計出入度數即可得到答案
*註意,如果強連通分量只有1個,答案應該是0而不是1
#include <bits/stdc++.h> #define ll long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define pp pair<int,int> #define rep(ii,a,b) for(int ii=a;ii<=b;ii++) #define per(ii,a,b) for(int ii=a;ii>=b;ii--) #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(a,b) cout<<#a<<‘[‘<<#b<<"]="<<a[b]<<endl using namespace std; const int maxn=1e5+10; const int maxm=1e6+10; const int INF=0x3f3f3f3f; int casn,n,m,k; int stk[maxn],top,cnt,dfn[maxn],low[maxn],numc,belong[maxn],vis[maxn]; struct node {int to,cost,next;}e[maxm];int head[maxn],nume; void add(int a,int b,int c=1){e[++nume]=(node){b,c,head[a]};head[a]=nume;} void tdfs(int now){ dfn[now]=low[now]=++cnt; stk[top++]=now; vis[now]=1; for(int i=head[now];i;i=e[i].next){ int to=e[i].to; if(!dfn[to]){tdfs(to);low[now]=min(low[now],low[to]);} else if(vis[to]) low[now]=min(low[now],dfn[to]); } if(low[now]==dfn[now]){ numc++; int to; do{ to=stk[--top]; belong[to]=numc; vis[to]=0; }while(to!=now); } } void tarjan(int numv=n){ for(int i=1;i<=numv;i++){ if(!dfn[i]) tdfs(i); } } void ginit(){ nume=top=numc=cnt=0; memset(head,0,sizeof head); memset(dfn,0,sizeof dfn); } int din[maxn],dout[maxn]; int main(){ //#define test #ifdef test freopen("in.txt","r",stdin);freopen("out.txt","w",stdout); #endif while(cin>>n>>m){ if(m==0) { cout<<n<<endl; continue; } ginit(); memset(din,0,sizeof din); memset(dout,0,sizeof dout); for(int i=0;i<m;i++){ int a,b; cin>>a>>b; add(a,b); } tarjan(); for(int i=1;i<=n;i++){ for(int j=head[i];j;j=e[j].next){ if(belong[i]==belong[e[j].to])continue; dout[belong[i]]++; din[belong[e[j].to]]++; } } int a=0,b=0; for(int i=1;i<=numc;i++){ if(din[i]==0)a++; if(dout[i]==0)b++; } if(numc==1) a=b=0; cout<<max(a,b)<<endl; } #ifdef test fclose(stdin);fclose(stdout);system("out.txt"); #endif return 0; }
Equivalent Sets HDU - 3836 2011多校I tarjan強連通分量