现在的位置: 首页 > 综合 > 正文

hdu 4635 (强连通缩点)

2018年03月18日 ⁄ 综合 ⁄ 共 1629字 ⁄ 字号 评论关闭

多校联赛4的一道题,,给一个有向图,问最多加多少条边后仍然不是强联通,以前总会遇到问最少加几条边让图成一个强连通图,比赛时自己就找到了答案,当时想着添加最多的边后一定是将原来的图连成两个强连通分量,而两个强连通分量间的边最多是两个联通分量的点数之积,再加上每个联通分量内部的点的边数就是所有的边数,再减去原来的边就是新加上的边了,把图强连通缩点后,求出每个出度或入度为0的联通分量为一个联通分量,剩余的所有联通分量连成一个联通分量形成的边数,取最大的。当时敲完代码提交wrong了,就怀疑自己的算法,自己又证明了一下,如果n个点,分为两个联通分量,一个点数为a,一个为b,边数就是a*(a-1)+b*(b-1)+a*b-m=n*n-a*b-n,所以要保证a*b尽量小,所以要选点数最小的入度或出度为0的联通分量为一个,剩余的点为一个联通分量,,,,最后发现自己的代码有问题,平常总习惯点坐标从0开始,所以写成了i<n,,,,,








#include<stdio.h>
#include<string.h>
#include<stack>
#define N 100010
using namespace std;
int belong[N],ins[N],low[N],dfs[N],idx,ans,head[N],num,n,m,in[N],out[N],cot[N];
struct edge
{
    int st,ed,next;
}E[N];
void addedge(int x,int y)
{
    E[num].st=x;
    E[num].ed=y;
    E[num].next=head[x];
    head[x]=num++;
}
stack<int>Q;
void Tarjan(int u)
{
    int i,v;
    dfs[u]=low[u]=idx++;
    ins[u]=1;
    Q.push(u);
    for(i=head[u];i!=-1;i=E[i].next)
    {
        v=E[i].ed;
        if(dfs[v]==-1)
        {
            Tarjan(v);
            low[u]=low[u]>low[v]?low[v]:low[u];
        }
        else if(ins[v]==1)
            low[u]=low[u]>dfs[v]?dfs[v]:low[u];
    }
    if(dfs[u]==low[u])
    {
        do
        {
            v=Q.top();
            Q.pop();
            ins[v]=0;
            belong[v]=ans;
            cot[ans]++;
        }while(v!=u);
        ans++;
    }
}
int main()
{
    int t,i,x,y,op=1,max;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));
        num=0;
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            addedge(x,y);
        }
        memset(dfs,-1,sizeof(dfs));
        memset(ins,0,sizeof(ins));
        memset(cot,0,sizeof(cot));
        idx=ans=0;
        for(i=1;i<=n;i++)
          if(dfs[i]==-1)
           Tarjan(i);
          printf("Case %d: ",op++); 
          if(ans==1)
          {printf("-1\n");continue;}
          memset(in,0,sizeof(in));
          memset(out,0,sizeof(out));
          for(i=0;i<num;i++)
          {
              x=belong[E[i].st];
              y=belong[E[i].ed];
              if(x==y)
              continue;
               out[x]++;
               in[y]++;
          }
          max=9999999;
          for(i=0;i<ans;i++)
          {
              if((in[i]==0||out[i]==0)&&max>cot[i])
                  max=cot[i];
          }
          printf("%d\n",n*n-max*(n-max)-n-m);
    }
    return 0;
}

抱歉!评论已关闭.