首页 > 代码库 > [tarjan] hdu 4635 Strongly connected

[tarjan] hdu 4635 Strongly connected

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4635

Strongly connected

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


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
 

Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:  5057 5056 5055 5054 5053 
 

Statistic | Submit | Discuss | Note

题目意思:

给一幅图,求最多增加多少边,可以使该图能够不满足强连通性。

解题思路:

分析知,最后肯定是两个完全图a,b,然后a中每个节点到b中每个节点都有一条有向边。整体考虑总的边数为a*(a-1)+b*(b-1)+a*b=n*n-n-a*b.

ans=n*n-n-a*b-m  n/m已知,所以让ans最大,就需让a*b最小,使得a,b差距最大。所以找最小的a或b.

tarjan求强连通,然后求出入度或出度为0的强连通分量,统计这些联通分量中节点数最小的a.

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 110000

int low[Maxn],dfn[Maxn],sta[Maxn],bc,sc,dep;
ll n,m;
int in[Maxn],dei[Maxn],deo[Maxn],nu[Maxn];
vector<vector<int> >myv;
bool iss[Maxn];

void tarjan(int cur)
{
    int ne;

    low[cur]=dfn[cur]=++dep;
    sta[++sc]=cur;
    iss[cur]=true;
    for(int i=0;i<myv[cur].size();i++)
    {
        ne=myv[cur][i];
        if(!dfn[ne])
        {
            tarjan(ne);
            if(low[ne]<low[cur])
                low[cur]=low[ne];
        }
        else if(iss[ne]&&dfn[ne]<low[cur])
            low[cur]=dfn[ne];
    }
    if(low[cur]==dfn[cur])
    {
        bc++;
        do
        {
            ne=sta[sc--];
            iss[ne]=false;
            in[ne]=bc;
            nu[bc]++;
        }while(ne!=cur);
    }
}
void solve()
{
    dep=sc=bc=0;
    memset(nu,0,sizeof(nu));
    memset(iss,false,sizeof(iss));
    memset(dfn,0,sizeof(dfn));
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i);
}

int main()
{
    //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   int t,kcas=0;

   scanf("%d",&t);
   while(t--)
   {
       scanf("%I64d%I64d",&n,&m);
       myv.clear();
       myv.resize(n+1);

       for(int i=1;i<=m;i++)
       {
           int a,b;
           scanf("%d%d",&a,&b);
           myv[a].push_back(b);
       }
       solve();
       if(bc==1)
       {
           printf("Case %d: -1\n",++kcas);
           continue;
       }
       memset(dei,0,sizeof(dei));
       memset(deo,0,sizeof(deo));

       for(int i=1;i<=n;i++)
            for(int j=0;j<myv[i].size();j++)
            {
               int ne=myv[i][j];
               if(in[ne]!=in[i])
               {
                   dei[in[ne]]++;
                   deo[in[i]]++;
               }
            }
      ll ans=INF;
      for(int i=1;i<=bc;i++)
      {
          if(!dei[i])
            ans=min(ans,(ll)nu[i]);
          else if(!deo[i])
            ans=min(ans,(ll)nu[i]);

      }
      printf("Case %d: %I64d\n",++kcas,n*n-n-ans*(n-ans)-m);
   }
    return 0;
}



[tarjan] hdu 4635 Strongly connected