您的位置:首页 > 其它

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);

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: