題解 P7251 【[JSOI2014] 強連通圖】
阿新 • • 發佈:2021-07-29
P7251 [JSOI2014] 強連通圖
題目大意:
給定個圖,回答兩個問題:
- 求圖中最大的強連通分量的大小
- 求新增多少條邊可使圖強連通。
solution:
\(1\) 非常好實現,直接 \(\text{tarjan}\) 求強聯通分量後取
\(\max \limits_{i=1}^{cnt\_scc}\{\text{size[ i ]}\}\) 。考慮 \(2\) 。一個強連通圖必然沒有入度為 \(0\) 和出度為 \(0\) 的點(點數大於 \(1\) ),在縮點後,我們只需要統計入度和出度為 \(0\) 的強連通分量的個數再取個 \(\max\) 就好了。
接下來是細節的處理:
在上文敘述中括號中的條件需要特判,即 \(\text{cnt\_scc}==1\)
1
0
看到這的同學,可以自己去寫程式碼了(tf口吻)
程式碼
#include<cstdio> using namespace std; const int N=1e5+5,M=3e5+5; int hd[N],nt[M],to[M],cnt; int dfn[N],low[N],of[N],st[N],size[N],top,lcnt,chuo; int ru[N],chu[N],ans; bool vis[N]; inline int Min(int a,int b){return a<=b?a:b;} inline int Max(int a,int b){return a>=b?a:b;} inline void tian(int a,int b){ to[++cnt]=b,nt[cnt]=hd[a],hd[a]=cnt; } inline void tarjan(int x){ st[++top]=x, vis[x]=1; dfn[x]=++chuo,low[x]=chuo; for(int i=hd[x];i;i=nt[i]){ int y=to[i]; if(!dfn[y]){ tarjan(y); low[x]=Min(low[x],low[y]); } else if(vis[y]) low[x]=Min(low[x],dfn[y]); } if(dfn[x]==low[x]){ lcnt++; while(1){ int y=st[top--]; of[y]=lcnt,vis[y]=0; size[lcnt]++; ans=Max(ans,size[lcnt]); if(x==y) break; } } } int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); tian(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); if(lcnt==1){ printf("1\n0"); return 0; } for(int x=1;x<=n;x++){ for(int i=hd[x];i;i=nt[i]){ int y=to[i]; if(of[x]!=of[y]) chu[of[x]]++,ru[of[y]]++; } } int rcnt=0,ccnt=0; for(int i=1;i<=lcnt;i++){ if(!ru[i]) rcnt++; if(!chu[i]) ccnt++; } printf("%d\n%d",ans,Max(rcnt,ccnt)); return 0; }