标签:
大致题意:
给出一个连通的无向图,求哪些点是割点,对于每个割点,求出去掉这个点后连通分量的个数。如果没有割点的话输出“ No SPF nodes”。
思路:
求割点用tarjan即可,然后要求删除割点后连通分量的个数,每次找到割点,再在从割点dfs即可,也可以直接在tarjan算法中记录child个数。那么如果割点是根,那么答案就是child,不是根的割点答案是child+1
//188K 0MS C++ 2121B
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
int head[N];
struct Edge
{
int v,next;
}es[N*N];
struct node
{
int u;
int cnt;
}ans[N];
int n;
int cnt;
int dfn[N],low[N];
int index,top=0;
bool vis[N];
bool book[N];
void tarjan(int u,int rt,int pa)
{
dfn[u]=low[u]=++index;
int child=0;
for(int i=head[u];~i;i=es[i].next)
{
int v=es[i].v;
if(dfn[v]==0)
{
tarjan(v,rt,u);
low[u]=min(dfn[u],low[v]);
if(low[v]>=dfn[u]) child++;
}
if(v!=pa) low[u]=min(dfn[u],low[v]);
}
if(u==rt&&child>1) ans[++top].u=u,ans[top].cnt=child;
else if(u!=rt&&child) ans[++top].u=u,ans[top].cnt=child+1;
}
void ini()
{
memset(head,-1,sizeof(head));
cnt=0;
n=-1;
memset(dfn,0,sizeof(dfn));
memset(book,0,sizeof(book));
top=index=0;
}
bool cmp(const node &a,const node&b)
{
return a.u<b.u;
}
int main()
{
int u,v;
int cas=0;
while(scanf("%d%d",&u,&v)== 2)
{
printf("Network #%d\n",++cas);
ini();
n=max(n,u);
n=max(v,n);
es[++cnt].v=v;
es[cnt].next=head[u];
head[u]=cnt;
es[++cnt].v=u;
es[cnt].next=head[v];
head[v]=cnt;
while(1)
{
scanf("%d",&u);
if(u==0) break;
scanf("%d",&v);
es[++cnt].v=v;
es[cnt].next=head[u];
head[u]=cnt;
es[++cnt].v=u;
es[cnt].next=head[v];
head[v]=cnt;
n=max(max(u,v),n);
}
for(int i=1;i<=n;i++)
if(dfn[i]==0) tarjan(i,i,-1);
sort(ans+1,ans+1+top,cmp);
if(top==0) printf(" No SPF nodes\n");
for(int i=1;i<=top;i++)
{
printf(" SPF node %d leaves %d subnets\n",ans[i].u,ans[i].cnt);
}
puts("");
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/45228173