hdu 4635 Strongly connected (tarjan强连通分量)
来源:互联网 发布:msdn win7 优化 编辑:程序博客网 时间:2024/05/21 11:08
题意:给你一个有向图,问在保证这个图无重边,无自环,且不是强连通图的情况下,最多可以添加多少条有向边
思路:分析可知,最终得到的图分为A,B两个部分,两部分各自为完全图,A中每个点都向B中每个点引一条有向边,B中每个点必定不存在通往A的有向边。这样可推得整个图的总边数为a*(a-1)+b*(b-1)+ab,需要添加的边数是a*(a-1)+b*(b-1)+ab-m。而a+b=n,化简得a*(a-1)+b*(b-1)+ab=n*n-n-a*b。ab=a*(n-a)=b*(n-b),若要让a*b尽量小,根据函数曲线,要求a和b尽量远离n/2。令b尽量小,则需要找到原图中入度为0或出度为0的强连通分量中点数最少的一个作为B部分,其余的作为A部分。
#include<iostream>#include<stack>#include<vector>#include<cstring>#include<string>using namespace std;const long long maxn=100001;const long long INF=0x3f3f3f3f;vector <long long> v[maxn];stack <long long> s;long long n,m,t,T,ans,sum,minn,visit,numa,numb;long long dfn[maxn],low[maxn],belong[maxn],stack[maxn],x[maxn],y[maxn],number[maxn],inn[maxn],outt[maxn];bool instack[maxn];void tarjan(long long x){ long long y,k,temp; visit++; dfn[x]=low[x]=visit; instack[x]=true; s.push(x); for(int i=0;i<v[x].size();i++) { y=v[x][i]; if(!dfn[y]) { tarjan(y); if(low[y]<low[x]) low[x]=low[y]; } else if(instack[y] && dfn[y]<low[x]) low[x]=dfn[y]; } // cout<<"x="<<x<<" dfn[x]="<<dfn[x]<<" low[x]="<<low[x]<<endl; if(dfn[x]==low[x]) { temp=0; if(!s.empty()) { sum++; while(!s.empty()) { temp++; k=s.top(); instack[k]=false; belong[k]=sum; s.pop(); if(k==x) break; } number[sum]=temp; // cout<<"number["<<sum<<"]="<<temp<<endl; } }}void solve(){ while(!s.empty()) s.pop(); visit=sum=0; minn=INF; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(inn,0,sizeof(inn)); memset(outt,0,sizeof(outt)); memset(belong,0,sizeof(belong)); memset(instack,0,sizeof(instack)); for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=m;i++) { if(belong[x[i]]==belong[y[i]]) continue; outt[belong[x[i]]]++; inn[belong[y[i]]]++; } for(int i=1;i<=sum;i++) if(inn[i]==0 || outt[i]==0) if(number[i]<minn) minn=number[i];}int main(){ cin>>T; t=0; while(T--) { cin>>n>>m; for(int i=1;i<=n;i++) v[i].clear(); for(int i=1;i<=m;i++) { cin>>x[i]>>y[i]; v[x[i]].push_back(y[i]); } solve(); if(sum==1) cout<<"Case "<<++t<<": "<<-1<<endl; else { numa=n-minn; numb=minn; ans=numa*(numa-1)+numb*(numb-1)+numa*numb-m; cout<<"Case "<<++t<<": "<<ans<<endl; // cout<<"min="<<minn<<endl<<"ans="<<ans<<endl; } } return 0;}
- hdu 4635 Strongly connected (tarjan强连通分量)
- hdu 4635 Strongly connected (强连通分量)
- hdu-4635-Strongly connected-强连通分量
- HDU 4635 Strongly connected(强连通分量)
- HDU 4635 Strongly connected(强连通分量)
- hdu 4635 Strongly connected (强连通分量缩点)
- HDU 4635 Strongly connected(强连通分量+缩点)
- HDU 4635 Strongly connected 强连通分量分解
- HDU-4635-Strongly connected(强连通分量)
- hdu 4635 Strongly connected(连通分量)
- hdu 4635 Strongly connected 强连通
- HDU 4635 Strongly connected 强连通
- 【强连通】 HDU 4635 Strongly connected
- HDU 4635 - Strongly connected(强连通)
- HDU 4635 Strongly connected(强连通)
- HDU 4635 Strongly connected 强连通
- HDU 4635 Strongly connected(强连通)经典
- hdu 4635 Strongly connected Kosaraju/Tarjan求强联通分量大小
- HDOJ 4628 - Pieces 状态压缩DP..枚举所有子集进行更新
- 容斥原理应用(求1~r中有多少个数与n互素)
- mysql pod 插入 乱码的解决方案
- 排序算法(个人总结)
- 05-php中的全局变量和静态变量
- hdu 4635 Strongly connected (tarjan强连通分量)
- hdu 2895 (水)
- C语言文件输入/输出 ACM改进版(用freopen函数方便检验)
- 浅析.NET
- c tips 待续、、、
- 正则表达式基础知识
- JS图片上传预览
- java学习笔记(一)
- 字节对齐重写malloc 和 free