HDU - 4635 Strongly connected(强连通缩点+数学+思维)
生活随笔
收集整理的這篇文章主要介紹了
HDU - 4635 Strongly connected(强连通缩点+数学+思维)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一個由n個點和m條邊構成的無向圖,現在問最多能添加幾條邊,能使得原圖仍然不是強連通圖,若原圖初始時就是強連通圖,直接輸出-1
題目分析:首先對于原圖來說,肯定會有一些集合中已經是強連通的了,我們可以先強連通縮點,再繼續操作,最優情況肯定是需要孤立一個點,然后剩下的點構成強連通分量,并且強連通分量中的每個點都對這個孤立的點連邊,假設孤立的點所代表的集合大小為x,其他點的總數為y,滿足x+y=n,這樣計算出來的答案就是x*(x-1)+y*(y-1)+x*y-m,到此為止直接枚舉每一個符合條件的集合作為孤立集合,計算答案,實時更新最大值就好了,至于滿足條件的點,必須是在邊上的點,意思就是出度或入度兩者中的一個必須為0才行,這樣就能根據數學公式計算最大值了
代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;const int M=1e5+100;struct Egde {int to,next; }edge1[M],edge2[M];int head1[N],head2[N],low[N],dfn[N],c[N],Stack[N],num,cnt,cnt2,cnt1,dcc,n,m,top,in[N],out[N];bool ins[N];vector<int>scc[N];void addedge1(int u,int v) {edge1[cnt1].to=v;edge1[cnt1].next=head1[u];head1[u]=cnt1++; }void addedge2(int u,int v) {edge2[cnt2].to=v;edge2[cnt2].next=head2[u];head2[u]=cnt2++; }void tarjan(int u) {dfn[u]=low[u]=++num;Stack[++top]=u;ins[u]=true;for(int i=head1[u];i!=-1;i=edge1[i].next){int v=edge1[i].to;if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(ins[v])low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){cnt++;int v;do{v=Stack[top--];ins[v]=false;c[v]=cnt;scc[cnt].push_back(v);}while(u!=v);} }void solve() {for(int i=1;i<=n;i++)//縮點 if(!dfn[i])tarjan(i); }void build()//縮點+連邊 {solve();for(int i=1;i<=n;i++){for(int j=head1[i];j!=-1;j=edge1[j].next){int u=i;int v=edge1[j].to;if(c[u]!=c[v]){addedge2(c[u],c[v]);out[c[u]]++;in[c[v]]++;}}} }void init() {for(int i=0;i<N;i++)scc[i].clear();top=cnt=cnt1=cnt2=num=dcc=0;memset(head2,-1,sizeof(head2));memset(head1,-1,sizeof(head1));memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));memset(c,0,sizeof(c));memset(ins,false,sizeof(ins));memset(in,0,sizeof(in));memset(out,0,sizeof(out)); }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--){init();scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);addedge1(u,v);}build();if(cnt==1){printf("Case %d: -1\n",++kase);continue;}LL ans=0;for(int i=1;i<=cnt;i++)if(in[i]==0||out[i]==0){int a=scc[i].size();int b=n-a;ans=max(ans,1LL*a*(a-1)+1LL*b*(b-1)+a*b-m);}printf("Case %d: %lld\n",++kase,ans);}return 0; }?
總結
以上是生活随笔為你收集整理的HDU - 4635 Strongly connected(强连通缩点+数学+思维)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU - 4612 Warm up(边
- 下一篇: POJ - 1904 King's Qu