HDU 4635 - Strongly connected(2013MUTC4-1004)(强连通分量)

t这道题在我们队属于我的范畴,最终因为最后一个环节想错了,也没搞出来

题解是这么说的:

 

最终添加完边的图,肯定可以分成两个部X和Y,其中只有X到Y的边没有Y到X的边,那么要使得边数尽可能的多,则X部肯定是一个完全图,Y部也是,同时X部中每个点到Y部的每个点都有一条边,假设X部有x个点,Y部有y个点,有x+y=n,同时边数F=x*y+x*(x-1)+y*(y-1),整理得:F=N*N-N-x*y,当x+y为定值时,二者越接近,x*y越大,所以要使得边数最多,那么X部和Y部的点数的个数差距就要越大,所以首先对于给定的有向图缩点,对于缩点后的每个点,如果它的出度或者入度为0,那么它才有可能成为X部或者Y部,所以只要求缩点之后的出度或者入度为0的点中,包含节点数最少的那个点,令它为一个部,其它所有点加起来做另一个部,就可以得到最多边数的图了

而我只是考虑到了最大边数,于是就去求最小点的强连通分量,以下是错误例子:

连通块A(10个点)->B(2个点)->C(10个点)

B是最小的强连通分量,而它无法往A或C加边,所以必须求入度或出度为0的连通块

 

#include <stdio.h>

#include <string.h>

#include <vector>

#include <stack>

#include <algorithm>

using namespace std;

#define LL long long

const int maxn=100010;

vector<int> G[maxn];

int n,m;

int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;

int in[maxn],out[maxn];

stack<int> S;



void dfs(int u){

    pre[u]=lowlink[u]=++dfs_clock;

    S.push(u);

    for(int i=0;i<G[u].size();i++)

    {

        int v=G[u][i];

        if(!pre[v]){

            dfs(v);

        lowlink[u]=min(lowlink[u],lowlink[v]);

        }

        else if(!sccno[v]){

            lowlink[u]=min(lowlink[u],pre[v]);

        }

    }

    if(lowlink[u]==pre[u])

    {

        scc_cnt++;

        for(;;){

            int x=S.top();S.pop();

            sccno[x]=scc_cnt;

            if(x==u)break;

        }

    }

}



void find_scc(int n){

    dfs_clock=scc_cnt=0;

    memset(sccno,0,sizeof(sccno));

    memset(pre,0,sizeof(pre));

    for(int i=0;i<n;i++)

        if(!pre[i])dfs(i);

}



int main()

{

    LL ct[100010];

    int T,x,y,cas=0;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%d%d",&n,&m);

        for(int i=0;i<n;i++)

            G[i].clear();

        for(int i=0;i<m;i++)

        {

            scanf("%d%d",&x,&y);

            G[x-1].push_back(y-1);

        }

        find_scc(n);

        printf("Case %d: ",++cas);

        if(scc_cnt==1)

        {

            printf("-1\n");

        }

        else

        {

            memset(ct,0,sizeof(ct));

            memset(in,0,sizeof(in));

            memset(out,0,sizeof(out));

            LL max=0;

            for(int i=0;i<n;i++)

            {

                ct[sccno[i]]++;

            }

            for(int i=0;i<n;i++)

            {

                for(int j=0;j<G[i].size();j++)

                {

                    if(sccno[i]!=sccno[G[i][j]])

                    {

                    out[sccno[i]]++;

                    in[sccno[G[i][j]]]++;

                    }

                }

            }

            for(int i=1;i<=scc_cnt;i++)

            {

                if(in[i]==0||out[i]==0)

                {

                   LL k=ct[i];

                   LL ans=k*(k-1)+(n-k)*(n-k-1)+k*(n-k)-m;

                   if(ans>max)max=ans;

                }

            }

            printf("%I64d\n",max);

        }

    }

    return 0;

}


 

 

你可能感兴趣的:(connect)