HDU 4635 Strongly connected 连通图

题目描述:

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 

题目分析:

题目大意就是有一个有向图,你可以至多加多少条边使这个有向图依然不能强连通。若原图就是强连通图,则输出-1。
先用Tarjan算连通分支,如果只有一个连通分支,说明这是强连通图,输出-1。
接下来把问题等价转化成一个完全图,减去最少的边使这个图不是强连通图。将各个强连通分量缩成点,去除所有强联通分量中含有点数最少的点的所有进边,就能得出答案。

代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

const int MAXN=100010;
const int INF= 0x3f3f3f3f;
typedef long long LL;
using namespace std;

struct Edge
{
    int to,next;
}edge[MAXN];

int head[MAXN],tot;
int low[MAXN],dfn[MAXN],stack[MAXN],belong[MAXN];
int index,top;
int scc;
bool instack[MAXN];
int num[MAXN];//各个强连通分量包含的点的个数
int id[MAXN],od[MAXN];//出度和入度

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}

void tarjan(int u)//kuangbin模板
{
    int v;
    low[u]=dfn[u]=++index;
    stack[top++]=u;
    instack[u]=true;
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        v=edge[i].to;
        if (!dfn[v])
        {
            tarjan(v);
            if (low[u]>low[v]) low[u]=low[v];
        }
        else if (instack[v] && low[u]>dfn[v]) low[u]=dfn[v];
    }
    if (low[u]==dfn[u])
    {
        scc++;
        do
        {
            v=stack[--top];
            instack[v]=false;
            belong[v]=scc;
            num[scc]++;
        }
        while(v!=u);
    }
}

void solve(int n)
{
    memset(dfn,0,sizeof(dfn));
    memset(instack,false,sizeof(instack));
    memset(num,0,sizeof(num));
    index=scc=top=0;
    for(int i=1; i<=n; i++)
    {
        if (!dfn[i]) tarjan(i);
    }
}
int T;
int n,m;
int main()
{
    scanf("%d",&T);
    for(int t=1; t<=T; t++)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=0; i

你可能感兴趣的:(图论)