TWO NODES
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
解题思路:
要求删掉两个点的连通分量,那么先枚举删掉一个点(不访问就行了),然后再对剩下的子图跑一遍tarjan。可以求出一个点删除之后,增加的连通分量的数量(也就是成为割点的次数)。如果是根节点要记得减1
然后再取max就行了。
AC代码:
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
using namespace std;
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define pd(n) printf("%d\n", n)
#define pc(n) printf("%c", n)
#define pdd(n,m) printf("%d %d", n, m)
#define pld(n) printf("%lld\n", n)
#define pldd(n,m) printf("%lld %lld\n", n, m)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sc(n) scanf("%c",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define mem(a,n) memset(a, n, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mod(x) ((x)%MOD)
#define gcd(a,b) __gcd(a,b)
#define lowbit(x) (x&-x)
#define pii map<int,int>
#define mk make_pair
#define rtl rt<<1
#define rtr rt<<1|1
#define Max(x,y) (x)>(y)?(x):(y)
#define int long long
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int MOD = 1e9 + 7;
const ll mod = 998244353;
const double eps = 1e-9;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
//const int inf = 0x3f3f3f3f;
inline int read(){int ret = 0, sgn = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')sgn = -1;ch = getchar();}
while (ch >= '0' && ch <= '9'){ret = ret*10 + ch - '0';ch = getchar();}
return ret*sgn;}
inline void Out(int a){if(a>9) Out(a/10);putchar(a%10+'0');}
int qpow(int m, int k, int mod){int res=1,t=m;while(k){if(k&1)res=res*t%mod;t=t*t%mod;k>>=1;}return res;}
ll gcd(ll a,ll b){return b==0?a : gcd(b,a%b);}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}
ll inv(ll x,ll m){return qpow(x,m-2,m)%m;}
const int N = 5e3+15;
vector<int> G[N];
int dfn[N],low[N],cnt[N];
int n,m;
int clk = 0;
void tarjan(int pos,int par,int del)
{
dfn[pos] = low[pos] = ++clk;
int nn = G[pos].size();
for(int i = 0 ; i < nn ; i ++)
{
int to = G[pos][i];
if(to == par || to == del) continue;
if(!dfn[to])
{
tarjan(to,pos,del);
low[pos] = min(low[pos],low[to]);
// 割点的判断 记录成为割点的次数,也就是删除后连通分量的个数(或者说是子树的个数)
if(low[to] >= dfn[pos])
cnt[pos]++;
}
else
low[pos] = min(low[pos],dfn[to]);
}
}
signed main()
{
while(~scanf("%lld%lld",&n,&m)){
for(int i = 0 ; i < n ; i ++)
G[i].clear();
for(int i = 0 ; i < m ; i ++)
{
int x,y;
scanf("%lld%lld",&x,&y);
G[x].pb(y);
G[y].pb(x);
}
int ans = 0;
for(int i = 0 ; i < n ; i ++)
{
memset(dfn,0,sizeof(dfn));
clk = 0;
for(int j = 0 ; j < n ; j ++) cnt[j] = 1;
int sum = 0;
for(int j = 0 ; j < n ; j ++)
{
if(i != j && !dfn[j])
{
sum ++; // 跑一遍就说明这也是一个连通分量 所以sum++
cnt[j] = 0; // 根节点 cnt 要减一 因为已经是根节点了,不会因为删掉而影响父结点的连通性(因为没有父亲节点),那么只要求子树就可以了。而如果不是 那么删掉就会影响父亲节点的连通性。
tarjan(j,-1,i);
}
}
for(int j = 0 ; j < n ; j ++)
if(i!=j)
ans = max(ans,sum+cnt[j]-1);
}
printf("%lld\n",ans);
}
}