HDU--Strongly connected--强连通缩点+思维

Strongly connected

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5179    Accepted Submission(s): 2058


 

Problem Description

Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the edges you can add that the graph is still a simple directed graph. Also, after you add these edges, this graph must NOT be strongly connected.
A simple directed graph is a directed graph having no multiple edges or graph loops.
A strongly connected digraph is a directed graph in which it is possible to reach any node starting from any other node by traversing edges in the direction(s) in which they point.

 

 

Input

The first line of date is an integer T, which is the number of the text cases.
Then T cases follow, each case starts of two numbers N and M, 1<=N<=100000, 1<=M<=100000, representing the number of nodes and the number of edges, then M lines follow. Each line contains two integers x and y, means that there is a edge from x to y.

 

 

Output

For each case, you should output the maximum number of the edges you can add.
If the original graph is strongly connected, just output -1.

 

 

Sample Input

 

3 3 3 1 2 2 3 3 1 3 3 1 2 2 3 1 3 6 6 1 2 2 3 3 1 4 5 5 6 6 4

 

 

Sample Output

 

Case 1: -1 Case 2: 1 Case 3: 15

 

 

Source

2013 Multi-University Training Contest 4

给出一个有向图,问是否强连通,强连通输出-1,否则求加最多的边,无重复边和自环,使得其还是不强连通。

假设我们现在进行缩点之后得到一些强连通块,将点数最少的X块单独拿出来,其他的合并为Y块。

那么此时可以有X*(X-1) X块强连通最多边+Y*(Y-1) Y块强连通最多边+X*Y X的每一个点向Y连一条边。此时是不是强连通的最多边,然后减去已经有的M,即为所求。

X*(X-1)+Y*(Y-1)-X*Y-M=N*N-N-X*Y-M 。所以要求X*Y最小值,X+Y=N,那么X 与 Y相差最大时符合条件。所以选择一个入度或出度等于0的且点最少的那个强连通块作为X。

#include
#include
#include
#include
#include
#define ll long long
using namespace std;
int dx[2]= {0,1};
int dy[2]= {1,0};
const int INF=99999999;
const int MAXN = 100000+66;
const int MAXM = 100000+66;
struct Edge
{
    int from,to,next;
} e[MAXM];
int dfn[MAXN],low[MAXN],head[MAXN],link[MAXN],visx,tot,tot_edge;
int n,nn,m,cnt,belong[MAXN],in[MAXN],out[MAXN],a[MAXN],sum[MAXN];
bool exist[MAXN];
void PrePare()
{
    cnt=0;
    visx=0;
    tot=0;
    memset(dfn,-1,sizeof dfn );
    memset(low,-1,sizeof low );
    memset(head,0,sizeof head );
    memset(link,0,sizeof link );
    memset(belong,0,sizeof belong );
    memset(exist,0,sizeof exist );
    memset(sum,0,sizeof sum );
    memset(in,0,sizeof in );
    memset(out,0,sizeof out );
}
void Add_Edge(int u,int v,int *head)
{
    e[++tot].to=v;
    e[tot].from=u;
    e[tot].next=head[u];
    head[u]=tot;
}
stack st;
void Tarjan(int u)
{
    dfn[u]=low[u]= ++visx;
    st.push(u);
    exist[u]=true;
    for(int i=head[u]; i; i=e[i].next)
    {
        int v=e[i].to;
        if(dfn[v]==-1)
        {
            Tarjan(v);
            low[u]=min(low[v],low[u]);
        }
        else if(exist[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        ++cnt;//强连通点的个数
        while(1)
        {
            int v=st.top();
            st.pop();
            exist[v]=0;
            belong[v]=cnt;//v这个
            //sum[cnt]+=a[v];//看这个缩点的权值
            if(v==u)
                break;
        }
    }
}
void new_Map()
{
    for(int i=1; i<=n; i++)
    {
        sum[belong[i]]++;
        for(int j=head[i]; j; j=e[j].next)
        {
            int v=e[j].to;
            if(belong[i]!=belong[v])
            {
                in[belong[v]]++;
                out[belong[i]]++;
            }
        }
    }
}
ll solve()
{
    if(cnt==1)
    {
        return -1;
    }
    else
    {
        new_Map();
        int ans=0;
        //
        int left=100000+1;
        for(int i=1; i<=cnt; i++)
        {
            if(in[i]==0||out[i]==0)
            {
                if(sum[i]

 

你可能感兴趣的:(ACM强连通分量有向图)