[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
 

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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章