世界真的很大
昨天晚上还有十分钟的时候开始写这道题,未果
今天上午考试下午讲课晚上好不容易有时间来写这道题,成功
犯了一个小小的错误不必深究
POJ的读入方式怎么这么恶心woc。。
看题先:
description:
无向图求割点和去除割点后连通分量的个数
input:
The input will contain the description of several networks. A network description will consist of pairs of integers, one pair per line, that identify connected nodes. Ordering of the pairs is irrelevant; 1 2 and 2 1 specify the same connection. All node numbers will range from 1 to 1000. A line containing a single zero ends the list of connected nodes. An empty network description flags the end of the input. Blank lines in the input file should be ignored.
output:
For each network in the input, you will output its number in the file, followed by a list of any SPF nodes that exist.
The first network in the file should be identified as “Network #1”, the second as “Network #2”, etc. For each SPF node, output a line, formatted as shown in the examples below, that identifies the node and the number of fully connected subnets that remain when that node fails. If the network has no SPF nodes, simply output the text “No SPF nodes” instead of a list of SPF nodes.
在这种一读就是板子题的东西下,**的出题人把考点放在了读入方式上。。。
想方设法读入完成后,这道题就是一个求割点然后判断每一个割点删去后会把联通图分成多少块
把图转化为DFS树之后相当于答案就是其子树个数+1,因为还有父亲边的方向。根节点需要特判一下,统计其有多少个子树,这个也可以在tarjan里面做到
完整代码:
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
struct edge
{
int u,v,last;
}ed[4000010];
int num=0,idx=0,cnt=0,tot=0,flag=1,son=0;
int head[10010],low[10010],dfn[10010],src[10010],fa[10010];
void add(int u,int v)
{
num++;
ed[num].v=v;
ed[num].last=head[u];
head[u]=num;
}
void tarjan(int u)
{
dfn[u]=low[u]=++idx;
for(int i=head[u];i;i=ed[i].last)
{
int v=ed[i].v;
if(i==(fa[u]^1)) continue ;
if(!dfn[v])
{
fa[v]=i;
tarjan(v);
low[u]=min(low[v],low[u]);
if(low[v]>=dfn[u])
{
if(u!=1) src[u]++;
else son++;
}
}
else low[u]=min(low[u],dfn[v]);
}
}
void init()
{
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(src,0,sizeof(src));
memset(fa,0,sizeof(fa));
num=1,idx=0,cnt=0,flag=1,son=0;
}
int main()
{
while(1)
{
init();
while(1)
{
int u,v;
scanf("%d",&u);
if(!u) break ;
scanf("%d",&v);
add(u,v),add(v,u);
cnt++;
}
if(cnt==0) break ;
tarjan(1);
printf("Network #%d\n",++tot);
if(son>1) src[1]=son-1;
for(int i=1;i<=1000;i++)
if(src[i])
{
flag=0;
printf(" SPF node %d leaves %d subnets\n",i,src[i]+1);
}
if(flag) printf(" No SPF nodes\n");
printf("\n");
}
return 0;
}
/*
EL PSY CONGROO
*/
嗯,就是这样
(P.S. 感觉最近题解越来越水了。。真不是因为我懒得写,只不过都是些板子题。。。主要目的是练手然后总结方法。。233)