HDU-4635-Strongly connected(强连通分量)
2016-05-13 14:48
351 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635
题意:问当前图加多少边成为最大不连通图。
题解:N个点,M条边,
当前图的最大不连通图即为加边后缩点为X,Y两个部分,
有X->Y或者Y->X的完全边且XY都为完全图;
则最大不连通图边数
F=x*y+x*(x-1)+y*(y-1)即 F=N*N-N-x*y
由于x+y=N,显然我们要使得abs(x-y)最大,这样直接选择缩点后入度或出度为0的且点最少的一个缩点为X。
答案显然是ans=max(ans,sum[i]*(sum[i]-1)+(n-sum[i])*(n-sum[i]-1)+sum[i]*(n-sum[i])-m);
题意:问当前图加多少边成为最大不连通图。
题解:N个点,M条边,
当前图的最大不连通图即为加边后缩点为X,Y两个部分,
有X->Y或者Y->X的完全边且XY都为完全图;
则最大不连通图边数
F=x*y+x*(x-1)+y*(y-1)即 F=N*N-N-x*y
由于x+y=N,显然我们要使得abs(x-y)最大,这样直接选择缩点后入度或出度为0的且点最少的一个缩点为X。
答案显然是ans=max(ans,sum[i]*(sum[i]-1)+(n-sum[i])*(n-sum[i]-1)+sum[i]*(n-sum[i])-m);
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e3+7; const int MAXM = 1e6+7; struct node { int v,next; } edge[MAXM]; int index,head[MAXM]; void add_edge(int u,int v) { edge[index].v=v; edge[index].next=head[u]; head[u]=index++; } int low[MAXN],stack_[MAXN],belong[MAXN],DFN[MAXN],sum[MAXN]; bool in_stack[MAXN]; int top,temp,poi,cir; void Tarjan(int u) { int p; DFN[u]=low[u]=++temp; in_stack[u]=1; stack_[top++]=u; for(int i=head[u]; i+1; i=edge[i].next) { int v=edge[i].v; if(!DFN[v]) { Tarjan(v); low[u]=min(low[u],low[v]); } else if(in_stack[v]) low[u]=min(low[u],DFN[v]); } if(DFN[u]==low[u]) { cir++; do { p=stack_[--top]; in_stack[p]=0; belong[p]=cir; sum[cir]++; } while(p!=u); } } int in[MAXN],out[MAXN]; void init() { index=cir=top=temp=0; memset(head,-1,sizeof(head)); memset(sum,0,sizeof(sum)); memset(DFN,0,sizeof(DFN)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); } int main() { int T,n,m; scanf("%d",&T); int cas=0; while(T--) { int a,b; init(); scanf("%d%d",&n,&m); for(int i=0; i<m; ++i) { scanf("%d%d",&a,&b); add_edge(a,b); } for(int i=1; i<=n; ++i) if(!DFN[i])Tarjan(i); if(cir<=1){printf("Case %d: -1\n",++cas);continue;} for(int i=1; i<=n; ++i) for(int j=head[i]; j+1; j=edge[j].next) { int v=edge[j].v; if(belong[i]!=belong[v]) { out[belong[i]]++; in[belong[v]]++; } } int ans=0; for(int i=1; i<=cir; ++i) if(!out[i]||!in[i]) { ans=max(ans,sum[i]*(sum[i]-1)+(n-sum[i])*(n-sum[i]-1)+sum[i]*(n-sum[i])-m); } printf("Case %d: %d\n",++cas,ans); } return 0; }
相关文章推荐
- 2014年第五届蓝桥杯C/C++程序设计本科B组决赛 Log大侠(编程大题)
- static全局变量与普通的全局变量的区别/static局部变量和普通局部变量的区别/static函数与普通函数的区别
- <<数学>>圆角矩形,矩形重叠(一)
- cocos2d-x lua 位操作
- Flask config.py 项目加载配置文件
- Linux中的文件描述符与打开文件之间的关系
- java中的线程-继承thread-实现runnable接口以及线程同步
- Selenium - Best practices
- 如何将一张披萨饼平均分成11份
- android-async-http框架库使用基础
- Leetcode 171. Excel Sheet Column Number
- dialog 中装listview并让每一个item分隔悬空,并具有radiobutton的效果
- 搭建wyquery环境
- android-SQLiteOpenHelper又称本地库
- 点击最小化按钮后,找不到AOPR软件了怎么办?
- Storyboard学习二(UIButton)
- CASE 工具有哪些
- 283. Move Zeroes
- android开源框架android-async-http使用
- 基于centos6.7的Ceph分布式文件系统安装指南