TWO NODES(HDU-4587)

Alex_McAvoy發表於2018-10-28

Problem Description

Suppose that G is an undirected graph, and the value of stab is defined as follows:

Among the expression,G-i, -j is the remainder after removing node i, node j and all edges that are directly relevant to the previous two nodes. cntCompent is the number of connected components of X independently.
Thus, given a certain undirected graph G, you are supposed to calculating the value of stab.

Input

The input will contain the description of several graphs. For each graph, the description consist of an integer N for the number of nodes, an integer M for the number of edges, and M pairs of integers for edges (3<=N,M<=5000).
Please note that the endpoints of edge is marked in the range of [0,N-1], and input cases ends with EOF.

Output

For each graph in the input, you should output the value of stab.

Sample Input

4 5
0 1
1 2
2 3
3 0
0 2

Sample Output

2

題意:給出一個 n 個點 m 條邊的無向圖,求從這個無向圖中刪除任意兩點後,所能得到的獨立連通分量的最大值

思路:容易想到從割點入手,因此第一個點先列舉所有點,第二個點通過 Tarjan 求割點的同時求出最大值,即原來用 iscut 表示是否為割點,現在用其來作為遍歷時成為割點的次數,那麼對於非根節點,刪去後剩餘個數為子樹個數加父節點個數,即:iscut[i]+1,對於根節點,由於沒有父節點,剩餘個數為子節點個數,即:iscut[i]

最後通過 max(iscut[i]+sum) 即可得出最優解

Source Program

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 20001
#define MOD 16007
#define E 1e-6
#define LL long long
using namespace std;
int n,m;
vector<int> G[N];
int dfn[N],low[N];
int iscut[N];
int block_cnt;
int Tarjan(int x,int father,int forbid){//forbid為禁止訪問的點
    int lowx=dfn[x]=++block_cnt;
    int child=0;

    for(int i=0;i<G[x].size();i++){
        int y=G[x][i];
        if(y==father || y==forbid)
            continue;

        if(dfn[y]==0){
            child++;

            int lowy=Tarjan(y,x,forbid);
            lowx=min(lowx,lowy);

            if(lowy>=dfn[x])
                iscut[x]++;
        }
        else
            lowx=min(lowx,dfn[y]);
    }

    if(father<0)
        iscut[x]--;

    return low[x]=lowx;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF&&(n+m)){
        for(int i=0;i<n;i++)
            G[i].clear();

        for(int i=0;i<m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }

        int res=-INF;
        for(int x=0;x<n;x++){//列舉所有點
            int sum=0;//刪除點x後的連通分量
            block_cnt=0;
            memset(dfn,0,sizeof(dfn));
            memset(iscut,0,sizeof(iscut));

            for(int y=0;y<n;y++){
                if(x!=y && dfn[y]==0){
                    sum++;
                    Tarjan(y,-1,x);
                }
            }

            for(int y=0;y<n;y++)
                res=max(res,sum+iscut[y]);
        }
        printf("%d\n",res);
    }
    return 0;
}

 

相關文章