poj1523
http://poj.org/problem?id=1523
割点简单题,问去掉一个割点后有多少个连通分支。
1 #include <stdio.h>
2 #include <string.h>
3 #define SIZE 1001
4 #define MIN(a,b) ((a)<(b)?(a):(b))
5 #define MAX(a,b) ((a)>(b)?(a):(b))
6 typedef struct NODE
7 {
8 int to;
9 NODE *next;
10 }node;
11 node edge[SIZE*SIZE],*head[SIZE],*p;
12 int n,m,num,count,cnt,block[SIZE],dfn[SIZE],low[SIZE];
13 bool g;
14 void bulid(int a,int b)
15 {
16 p->to=b;
17 p->next=head[a];
18 head[a]=p++;
19 p->to=a;
20 p->next=head[b];
21 head[b]=p++;
22 }
23 void tarjan(int key)
24 {
25 dfn[key]=low[key]=++cnt;
26 for(node *tmp=head[key];tmp;tmp=tmp->next)
27 {
28 if(!dfn[tmp->to])
29 {
30 tarjan(tmp->to);
31 if(dfn[key]<=low[tmp->to])
32 ++block[key]; //产生一个连通分支
33 else
34 low[key]=MIN(low[key],low[tmp->to]);
35 }
36 else
37 low[key]=MIN(low[key],dfn[tmp->to]);
38 }
39 }
40 void init()
41 {
42 memset(dfn,0,sizeof(dfn));
43 memset(low,0,sizeof(low));
44 memset(head,NULL,sizeof(head));
45 num=0;
46 g=false;
47 }
48 int main()
49 {
50 count=num=0;
51 while(scanf("%d",&n)==1&&n)
52 {
53 scanf("%d",&m);
54 p=edge;
55 bulid(n,m);
56 num=MAX(MAX(n,m),num);
57 while(scanf("%d",&n)==1&&n)
58 {
59 scanf("%d",&m);
60 bulid(n,m);
61 num=MAX(MAX(n,m),num);
62 }
63 for(int i=1;i<=num;++i)
64 block[i]=1;
65 cnt=0;
66 block[1]=0; //根一定会被认定为割点所以设连通数为0
67 tarjan(1);
68 printf("Network #%d\n",++count);
69 for(int i=1;i<=num;++i)
70 if(block[i]>1)
71 {
72 printf(" SPF node %d leaves %d subnets\n",i,block[i]);
73 g=true;
74 } //判断是否具有割点,若有割点其连通数一定大于1
75 if(!g)
76 printf(" No SPF nodes\n");
77 printf("\n");
78 init();
79 }
80 return 0;
81 }