/*
在一个图中,删除两个点以后,问图最多能变成多少块?
思路:先枚举删除的第一个点del,然后从剩下的点中dfs求割点,iscut[u]记录有多少个连通分支可以使得u成为割点,
那么删除u后该块就被分为了iscut[u]+1块(根节点为割点则应被分为iscut[u]块,为保持形式统一令iscut[root]--),
在dfs求割点的同时求出删去del之后整个图将被分为的块数res,则res+iscut[u]则为当前的块数ans,在枚举删除点的
过程当中求出最大的ans即为答案。
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
const int maxn = 5000 + 5;
int low[maxn],pre[maxn],iscut[maxn];
int n,m,del,dfs_clock;
vector<int>G[maxn];
int dfs(int u,int fa)
{
int lowu = pre[u] = ++dfs_clock;
int child = 0;
for(int i=0;i<G[u].size();i++){
int v = G[u][i];
if(v==del) continue;
if(!pre[v]){
++child;
int lowv = dfs(v,u);
lowu = min(lowu,lowv);
if(lowv >= pre[u]){
++iscut[u]; //每当有一个子分支可以使u为割点,++iscut[u];
}
}
else if(pre[v]<pre[u] && v != fa){
lowu = min(lowu,pre[v]);//一开始wa的不明所以,这里写成了 int lowu = min(lowu,pre[v]);
}
}
if(fa<0) --iscut[u]; //对于根节点,为保持形式统一令--iscut[u]
low[u] = lowu;
// if(fa<0&&iscut[u]) ans = max(ans,iscut[u]);
// else if(fa>0&&iscut[u]) ans = max(ans,iscut[u]+1);
return lowu;
}
int main()
{
//freopen("D:\\professional debugging\\in6.txt","r",stdin);
//freopen("D:\\professional debugging\\out62.txt","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF){
int x,y;
for(int i = 0;i<=n;i++) G[i].clear();
for(int i = 0;i<m;i++){
scanf("%d%d",&x,&y);
G[x+1].push_back(y+1);
G[y+1].push_back(x+1);
}
int res,ans=-1;
for(del = 1;del<=n;++del){
mem(pre,0); mem(low,0); mem(iscut,0);
dfs_clock = 0;
res = 0;
for(int i = 1;i<=n;i++){
if(!pre[i]&&i!=del){
dfs(i,-1);
++res;
}
}
for(int i=1;i<=n;i++){
if(i!=del){
ans = max(ans,res + iscut[i]);
}
}
}
printf("%d\n",ans);
}
return 0;
}
在一个图中,删除两个点以后,问图最多能变成多少块?
思路:先枚举删除的第一个点del,然后从剩下的点中dfs求割点,iscut[u]记录有多少个连通分支可以使得u成为割点,
那么删除u后该块就被分为了iscut[u]+1块(根节点为割点则应被分为iscut[u]块,为保持形式统一令iscut[root]--),
在dfs求割点的同时求出删去del之后整个图将被分为的块数res,则res+iscut[u]则为当前的块数ans,在枚举删除点的
过程当中求出最大的ans即为答案。
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
const int maxn = 5000 + 5;
int low[maxn],pre[maxn],iscut[maxn];
int n,m,del,dfs_clock;
vector<int>G[maxn];
int dfs(int u,int fa)
{
int lowu = pre[u] = ++dfs_clock;
int child = 0;
for(int i=0;i<G[u].size();i++){
int v = G[u][i];
if(v==del) continue;
if(!pre[v]){
++child;
int lowv = dfs(v,u);
lowu = min(lowu,lowv);
if(lowv >= pre[u]){
++iscut[u]; //每当有一个子分支可以使u为割点,++iscut[u];
}
}
else if(pre[v]<pre[u] && v != fa){
lowu = min(lowu,pre[v]);//一开始wa的不明所以,这里写成了 int lowu = min(lowu,pre[v]);
}
}
if(fa<0) --iscut[u]; //对于根节点,为保持形式统一令--iscut[u]
low[u] = lowu;
// if(fa<0&&iscut[u]) ans = max(ans,iscut[u]);
// else if(fa>0&&iscut[u]) ans = max(ans,iscut[u]+1);
return lowu;
}
int main()
{
//freopen("D:\\professional debugging\\in6.txt","r",stdin);
//freopen("D:\\professional debugging\\out62.txt","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF){
int x,y;
for(int i = 0;i<=n;i++) G[i].clear();
for(int i = 0;i<m;i++){
scanf("%d%d",&x,&y);
G[x+1].push_back(y+1);
G[y+1].push_back(x+1);
}
int res,ans=-1;
for(del = 1;del<=n;++del){
mem(pre,0); mem(low,0); mem(iscut,0);
dfs_clock = 0;
res = 0;
for(int i = 1;i<=n;i++){
if(!pre[i]&&i!=del){
dfs(i,-1);
++res;
}
}
for(int i=1;i<=n;i++){
if(i!=del){
ans = max(ans,res + iscut[i]);
}
}
}
printf("%d\n",ans);
}
return 0;
}