洛谷P3388 【模板】割点(割顶)
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=100009;
struct node {
int to,nxt;
} e[2*maxn];
int n,m,cnt=0,index=0,head[maxn],dfn[maxn],low[maxn],iscut[maxn],ans=0;
void add(int u,int v) {
e[++cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
void tarjan(int u,int fa) {
int child=0;
dfn[u]=low[u]=++index;
// cout<<"dfs "<<dfn[u]<<" "<<low[u]<<endl;
for(int i=head[u]; i>0; i=e[i].nxt) {
int v=e[i].to;
if(!dfn[v]) {
child++;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(fa>0&&low[v]>=dfn[u]) {
if(!iscut[u])++ans;//一个顶点可能被标记多次
iscut[u]=1;
// cout<<"df u"<<u<<" ans"<<ans<<endl;
}
} else if(dfn[v]<dfn[u]&&v!=fa)
low[u]=min(low[u],dfn[v]);
}
//cout<<u<<" child "<<child<<endl;
if(fa<0&&child>1) {
//if(!iscut[u])
++ans;//根节点不可能被统计多次
iscut[u]=1;
// cout<<"fa "<<u<<endl;
}
}
int main() {
cin>>n>>m;
int u,v;
for(int i=1; i<=m; i++) {
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i=1; i<=n; i++)
if(!dfn[i])tarjan(i,-1);
printf("%d\n",ans);
for(int i=1; i<=n; i++)
if(iscut[i])cout<<i<<" ";
}
poj2117,题目大意,给定一个图,删除一个点后,最多有多少连通块。
三种情况:
1:所有点是独立点,总数-1;
2:没有割点
3:删除链接儿子数最多的割点。
参考代码:
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int maxn=10009;
struct node {
int to,nxt;
} e[20*maxn];
int n,m,cnt=0,index=0,head[maxn],dfn[maxn],low[maxn],iscut[maxn],ans=0;
void add(int u,int v) {
e[++cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
int tarjan(int u,int fa) {
int child=0;
dfn[u]=low[u]=++index;
// cout<<"dfs "<<dfn[u]<<" "<<low[u]<<endl;
for(int i=head[u]; i>0; i=e[i].nxt) {
int v=e[i].to;
if(!dfn[v]) {
child++;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(fa>0&&low[v]>=dfn[u])
iscut[u]++;
} else if(dfn[v]<dfn[u]&&v!=fa)
low[u]=min(low[u],dfn[v]);
}
//cout<<u<<" child "<<child<<endl;
if(fa<0)
iscut[u]=child-1;
return 0;
}
int main() {
while(scanf("%d%d",&n,&m)==2) {
if(n==0&&m==0)return 0;
memset(head,0,sizeof(head));
memset(e,0,sizeof(e));
memset(iscut,0,sizeof(iscut));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
int u,v;
cnt=0;
for(int i=1; i<=m; i++) {
scanf("%d%d",&u,&v);
++u,++v;
add(u,v);
add(v,u);
}
int un=0;
ans=-1;
for(int i=1; i<=n; i++) {
if(!dfn[i])tarjan(i,-1),un++;
}
for(int i=1; i<=n; i++)ans=max(ans,iscut[i]);
cout<<un+ans<<endl;
}
}