http://poj.org/problem?id=1523
题意: 求 无向图的 个点,以及 将个点 去掉后 图 被分成 几个联通块;
题解: tarjan 。
1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<string>
11 #define Min(a,b) a<b?a:b
12 #define Max(a,b) a>b?a:b
13 #define CL(a,num) memset(a,num,sizeof(a));
14 #define eps 1e-6
15 #define inf 10001000
16
17 #define ll __int64
18
19 #define read() freopen("data.txt","r",stdin) ;
20 #define inf 9999999
21 using namespace std;
22
23 const double pi = acos(-1.0);
24 const int maxn = 1010;
25 #define N 30
26 int n , m ;
27 int dfn[maxn];// 记录 入栈的次序;
28 int low[maxn];// 记录 最小的 可以到达 的次序
29 int stack[maxn] ;//栈
30 int instack[maxn];//记录 是否在栈中
31 int num ;// 入栈的次序
32 int top; // 栈顶
33 int bcnt ; // 所点的 代表 序号
34 int belong[maxn];// 记录每个节点所属 的 缩点号;
35 vector<int>g[maxn] ;
36 int ans[maxn] ;
37 int in[maxn],out[maxn] ;
38 void tarjan(int a)
39 {
40 int j ,i, k;
41 dfn[a] = low[a]= ++num ;
42
43 stack[++top] = a;
44 instack[a] = 1 ;
45 for(i = 0 ; i < g[a].size();i++)
46 {
47 int k = g[a][i] ;
48 if(!dfn[k])
49 {
50 tarjan(k) ;
51 if(low[a] > low[k]) low[a] = low[k] ;
52 if( low[k] >= dfn[a]) ans[a]++ ;//记录 可以 分成的联通块数
53 }
54 else
55 {
56 if(instack[k] && dfn[k] < low[a]) low[a] = dfn[k] ;
57 }
58
59 }
60
61
62
63 }
64
65 int solve(int root)
66 {
67 int i , j;
68 CL(instack,0);
69 CL(belong,0) ;
70 CL(dfn,0) ;
71 CL(low,0) ;
72 num = bcnt = top = 0 ;
73 tarjan(root);
74
75 if(bcnt > 1) return 0;
76 else return 1 ;
77 }
78
79 int main()
80 {
81 int i ,a,b,t,j,mi,mx;
82 int cas = 0 ;
83 //read() ;
84 while(scanf("%d",&a)!=EOF)
85 {
86
87 if(a == 0) break;
88 if(cas > 0)printf("\n") ;
89
90
91 for(i = 0; i < maxn;i++) g[i].clear() ;
92
93 scanf("%d",&b);
94
95 if(a > b) mi = b;
96 else mi = a;
97
98 if(a > b) mx = a;
99 else mx = b;
100 g[a].push_back(b) ;
101 g[b].push_back(a) ;
102
103 while(scanf("%d",&a)!=EOF)
104 {
105 if(a == 0)break ;
106 scanf("%d",&b);
107 g[a].push_back(b) ;
108 g[b].push_back(a) ;
109
110 if(mi > a) mi = a;
111 if(mi > b) mi = b ;
112
113 if(mx < a) mx = a;
114 if(mx < b) mx = b;
115
116
117 }
118 //CL(in,0);
119 //CL(out,0) ;
120 CL(ans,0) ;
121
122
123
124 solve(mi) ;
125 printf("Network #%d\n",++cas) ;
126
127
128 ans[mi] -- ;// 因为 根没有 入边 ,所以 要减 1( ,下面的 有加 1)
129 int sum = 0 ;
130 for(i = mi ;i<= mx;i++)
131 {
132 //printf("%d -------\n",low[i]) ;
133 if(ans[i] > 0)
134 {
135 sum++ ;
136 printf(" SPF node %d leaves %d subnets\n",i,ans[i] + 1) ;
137 }
138 }
139
140
141
142 if(sum == 0)printf(" No SPF nodes\n");
143
144
145 }
146
147
148 }
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<string>
11 #define Min(a,b) a<b?a:b
12 #define Max(a,b) a>b?a:b
13 #define CL(a,num) memset(a,num,sizeof(a));
14 #define eps 1e-6
15 #define inf 10001000
16
17 #define ll __int64
18
19 #define read() freopen("data.txt","r",stdin) ;
20 #define inf 9999999
21 using namespace std;
22
23 const double pi = acos(-1.0);
24 const int maxn = 1010;
25 #define N 30
26 int n , m ;
27 int dfn[maxn];// 记录 入栈的次序;
28 int low[maxn];// 记录 最小的 可以到达 的次序
29 int stack[maxn] ;//栈
30 int instack[maxn];//记录 是否在栈中
31 int num ;// 入栈的次序
32 int top; // 栈顶
33 int bcnt ; // 所点的 代表 序号
34 int belong[maxn];// 记录每个节点所属 的 缩点号;
35 vector<int>g[maxn] ;
36 int ans[maxn] ;
37 int in[maxn],out[maxn] ;
38 void tarjan(int a)
39 {
40 int j ,i, k;
41 dfn[a] = low[a]= ++num ;
42
43 stack[++top] = a;
44 instack[a] = 1 ;
45 for(i = 0 ; i < g[a].size();i++)
46 {
47 int k = g[a][i] ;
48 if(!dfn[k])
49 {
50 tarjan(k) ;
51 if(low[a] > low[k]) low[a] = low[k] ;
52 if( low[k] >= dfn[a]) ans[a]++ ;//记录 可以 分成的联通块数
53 }
54 else
55 {
56 if(instack[k] && dfn[k] < low[a]) low[a] = dfn[k] ;
57 }
58
59 }
60
61
62
63 }
64
65 int solve(int root)
66 {
67 int i , j;
68 CL(instack,0);
69 CL(belong,0) ;
70 CL(dfn,0) ;
71 CL(low,0) ;
72 num = bcnt = top = 0 ;
73 tarjan(root);
74
75 if(bcnt > 1) return 0;
76 else return 1 ;
77 }
78
79 int main()
80 {
81 int i ,a,b,t,j,mi,mx;
82 int cas = 0 ;
83 //read() ;
84 while(scanf("%d",&a)!=EOF)
85 {
86
87 if(a == 0) break;
88 if(cas > 0)printf("\n") ;
89
90
91 for(i = 0; i < maxn;i++) g[i].clear() ;
92
93 scanf("%d",&b);
94
95 if(a > b) mi = b;
96 else mi = a;
97
98 if(a > b) mx = a;
99 else mx = b;
100 g[a].push_back(b) ;
101 g[b].push_back(a) ;
102
103 while(scanf("%d",&a)!=EOF)
104 {
105 if(a == 0)break ;
106 scanf("%d",&b);
107 g[a].push_back(b) ;
108 g[b].push_back(a) ;
109
110 if(mi > a) mi = a;
111 if(mi > b) mi = b ;
112
113 if(mx < a) mx = a;
114 if(mx < b) mx = b;
115
116
117 }
118 //CL(in,0);
119 //CL(out,0) ;
120 CL(ans,0) ;
121
122
123
124 solve(mi) ;
125 printf("Network #%d\n",++cas) ;
126
127
128 ans[mi] -- ;// 因为 根没有 入边 ,所以 要减 1( ,下面的 有加 1)
129 int sum = 0 ;
130 for(i = mi ;i<= mx;i++)
131 {
132 //printf("%d -------\n",low[i]) ;
133 if(ans[i] > 0)
134 {
135 sum++ ;
136 printf(" SPF node %d leaves %d subnets\n",i,ans[i] + 1) ;
137 }
138 }
139
140
141
142 if(sum == 0)printf(" No SPF nodes\n");
143
144
145 }
146
147
148 }