hdu4635 非强连通图最多加多少条边使仍然是强连通图 :tarjan缩点
在纸上画一下可以发现,最终可以加成两部分强连通,然后一部分->另一部分
thinking
所以就可以利用tarjan来缩点,然后找一个强连通分量使他的入度或者出度为0,可以加到边数为x1*(x1-1)+x2*(x2-1)+x1*x2,减去m就是能加的边
选取最大的==
------------------------------------------
这场先写5题,还有几题看上去挺好写的下次继续补了===
1 #include<stdio.h> 2 #include<vector> 3 #include<stack> 4 #include<string.h> 5 #include<algorithm> 6 #define maxn 100005 7 using namespace std; 8 stack<int>s; 9 vector<int>G[maxn]; 10 int pre[maxn],lowlink[maxn],sccno[maxn]; 11 int dfs_clock,scc_cnt; 12 int cnt[maxn],into[maxn],outo[maxn]; 13 void dfs(int u) 14 { 15 int i,v,tmp; 16 pre[u]=lowlink[u]=++dfs_clock; 17 s.push(u); 18 for (i=0;i<G[u].size();i++) 19 { 20 v=G[u][i]; 21 if (!pre[v]) 22 { 23 dfs(v); 24 lowlink[u]=min(lowlink[u],lowlink[v]); 25 } 26 else if (!sccno[v]) 27 lowlink[u]=min(lowlink[u],pre[v]); 28 } 29 if (lowlink[u]==pre[u]) 30 { 31 scc_cnt++; tmp=0; 32 while (1) 33 { 34 v=s.top(); s.pop(); 35 tmp++; 36 sccno[v]=scc_cnt; 37 if (v==u) break; 38 } 39 cnt[scc_cnt]=tmp; 40 } 41 } 42 int main() 43 { 44 int T,t,i,j,n,m,x,y,ans,x1,x2; 45 scanf("%d",&T); 46 for (t=1;t<=T;t++) 47 { 48 scanf("%d%d",&n,&m); 49 for (i=1;i<=n;i++) G[i].clear(); 50 for (i=1;i<=m;i++) 51 { 52 scanf("%d%d",&x,&y); 53 G[x].push_back(y); 54 } 55 dfs_clock=scc_cnt=0; 56 memset(sccno,0,sizeof(sccno)); 57 memset(pre,0,sizeof(pre)); 58 for (i=1;i<=n;i++) 59 if (!pre[i]) dfs(i); 60 printf("Case %d: ",t); 61 if (scc_cnt==1) printf("-1\n"); 62 else{ 63 memset(into,0,sizeof(into)); 64 memset(outo,0,sizeof(outo)); 65 for (i=1;i<=n;i++) 66 for (j=0;j<G[i].size();j++) 67 if (sccno[i]!=sccno[G[i][j]]) 68 { 69 into[sccno[G[i][j]]]++; 70 outo[sccno[i]]++; 71 } 72 ans=0; 73 for (i=1;i<=scc_cnt;i++) 74 if (!into[i]||!outo[i]) 75 { 76 x1=cnt[i]; x2=n-cnt[i]; 77 ans=max(ans,x1*x2+x1*(x1-1)+x2*(x2-1)-m); 78 } 79 printf("%d\n",ans); 80 } 81 } 82 return 0; 83 }