您的位置:首页 > 其它

[poj] 1523 SPF

2017-11-17 15:47 232 查看

原题

这是一道点双联通分量。
对于一个割点来说,在搜索他所分割的块与他的连边一定会使这个割点满足割点条件,也就是这时候讲这个割点所分割出来的块+1即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 500010
#define N 1010
using namespace std;
int n,m,a,b,cnt,sub,head
,dfn
,low
,t,is_AP
,num;
bool vis
;
struct hhh
{
int to,next;
}edge[2*M];

int read()
{
int ans=0,fu=1;
char j=getchar();
for (;(j<'0' || j>'9') && j!='-';j=getchar()) ;
if (j=='-') j=getchar(),fu=-1;
for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
return ans*fu;
}

void add(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}

void Tarjan(int u,int f)
{
int child=0;
dfn[u]=low[u]=++t;
for (int i=head[u],v;i;i=edge[i].next)
{
v=edge[i].to;
if (v==f) continue;
if (!dfn[v])
{
child++;
Tarjan(v,u);
low[u]=min(low[u],low[v]);
if (low[v]>=dfn[u] && f!=0)
{
if (!is_AP[u]) num++;
is_AP[u]++;
}
}
else low[u]=min(low[u],dfn[v]);
}
if (f==0 && child>1) is_AP[u]=child,num++;
else if (is_AP[u]) is_AP[u]++;
}

int main()
{
while (~scanf("%d",&a) && a!=0)
{
memset(dfn,0,sizeof(dfn));
memset(vis,0,sizeof(vis));
memset(head,0,sizeof(head));
memset(is_AP,0,sizeof(is_AP));
cnt=1;
t=0;
sub++;
b=read();
add(a,b);
add(b,a);
num=0;
vis[a]=vis[b]=1;
n=2;
while (~scanf("%d",&a) && a!=0)
{
b=read();
add(a,b);
add(b,a);
if (!vis[a]) n++,vis[a]=1;
if (!vis[b]) n++,vis[b]=1;
}
for (int i=1;i<=n;i++)
if (!dfn[i]) Tarjan(i,0);
printf("Network #%d\n",sub);
if (!num) printf("  No SPF nodes\n");
for (int i=1;i<=n;i++)
if (is_AP[i]) printf("  SPF node %d leaves %d subnets\n",i,is_AP[i]);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: