3177

1 /*
2 每两点之间有环存在
3
4 如果有一个环,所有的顶点都在这个环上,那么也就满足了
5
6 3352相似
7
8 找出桥,把不含桥的连通分量缩点,构造成一颗树,树种度为1的点为x个,(x+1)/2;
9 缩点是用并查集来做的。
10 */
11 // include file
12 #include <cstdio>
13 #include <cstdlib>
14 #include <cstring>
15 #include <cmath>
16 #include <cctype>
17 #include <ctime>
18
19 #include <iostream>
20 #include <sstream>
21 #include <fstream>
22 #include <iomanip>
23 #include <bitset>
24
25 #include <algorithm>
26 #include <string>
27 #include <vector>
28 #include <queue>
29 #include <set>
30 #include <list>
31 #include <functional>
32
33 using namespace std;
34
35 // typedef
36 typedef long long LL;
37 typedef unsigned long long ULL;
38 typedef __int64 Bint;
39
40 //
41 #define read freopen("in.txt","r",stdin)
42 #define write freopen("out.txt","w",stdout)
43 #define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
44 #define FORj(a,b,c) for(int j=(a);j<(b);j+=c)
45 #define FORk(a,b,c) for(int k=(a);k<(b);k+=c)
46 #define FORp(a,b,c) for(int p=(a);p<(b);p+=c)
47 #define FORii(a,b,c) for(int ii=(a);ii<(b);ii+=c)
48 #define FORjj(a,b,c) for(int jj=(a);jj<(b);jj+=c)
49 #define FORkk(a,b,c) for(int kk=(a);kk<(b);kk+=c)
50
51 #define FF(i,a) for(int i=0;i<(a);i++)
52 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
53
54 #define Z(a) (a<<1)
55 #define Y(a) (a>>1)
56
57 const double eps = 1e-6;
58 const double INFf = 1e10;
59 const int INFi = 1000000000;
60 const double Pi = acos(-1.0);
61
62 template<class T> inline T sqr(T a){return a*a;}
63 template<class T> inline T TMAX(T x,T y)
64 {
65 if(x>y) return x;
66 return y;
67 }
68 template<class T> inline T TMIN(T x,T y)
69 {
70 if(x<y) return x;
71 return y;
72 }
73 template<class T> inline void SWAP(T &x,T &y)
74 {
75 T t = x;
76 x = y;
77 y = t;
78 }
79 template<class T> inline T MMAX(T x,T y,T z)
80 {
81 return TMAX(TMAX(x,y),z);
82 }
83
84
85 // code begin
86 #define MAXN 5010
87 int N,M;
88 struct node1
89 {
90 int s;
91 int e;
92 int next;
93 };
94 struct node2
95 {
96 int next;
97 };
98 // link
99 node1 mem[MAXN*4];
100 node2 G[MAXN];
101
102 // disjoint-set
103 int father[MAXN],rank[MAXN];
104
105 // edge_bcc_tarjan
106 bool used[MAXN];
107 int dfn[MAXN];
108 int low[MAXN];
109 int deg[MAXN]; // 无向图的度数
110 int cnt;
111
112 void Init()
113 {
114 FORi(1,N+1,1)
115 {
116 father[i] = i;
117 rank[i] = 1;
118 }
119 }
120
121 int Find(int i)
122 {
123 if(father[i]!=i)
124 father[i] = Find(father[i]);
125 return father[i];
126 }
127
128 void Joint(int a,int b)
129 {
130 a = Find(a);
131 b = Find(b);
132 if(rank[a]>rank[b])
133 {
134 father[b] = a;
135 rank[a] += rank[b];
136 }
137 else
138 {
139 father[a] = b;
140 rank[b] += rank[a];
141 }
142 }
143
144 void Add_edge(int lo,int s,int e)
145 {
146 //需要判重边
147 int dx = G[s].next;
148 while(dx!=-1)
149 {
150 if(mem[dx].e==e) return;
151 dx = mem[dx].next;
152 }
153 mem[lo].e = e;
154 mem[lo].next=G[s].next;
155 G[s].next = lo;
156 }
157
158 void Edge_Bcc_Tarjan(int i,int fa)
159 {
160 dfn[i] = cnt;
161 low[i] = cnt;
162 used[i] = true;
163 cnt++;
164
165 //printf("链表:%d\n",i);
166 int dx = G[i].next;
167 while(dx!=-1)
168 {
169 int nx = mem[dx].e;
170 //printf("%d\n",nx);
171 if( !used[nx] )
172 {
173 Edge_Bcc_Tarjan(nx,i);
174 low[i] = TMIN(low[i],low[nx]);
175 // low[nx] > dfn[i] 时为割边
176 if( !( low[nx]>dfn[i] ))
177 {
178 Joint(nx,i);
179 }
180 }
181 else if(nx!=fa)
182 {
183 low[i] = TMIN(low[i],dfn[nx]);
184 }
185 dx = mem[dx].next;
186
187 }
188 }
189
190 void Shrink(int &bcc)
191 {
192 int a,b,dx;
193 FORi(1,N+1,1)
194 {
195 a = Find(i);
196 dx = G[i].next;
197 while(dx!=-1)
198 {
199 b = Find(mem[dx].e);
200 if(a!=b)
201 {
202 if(b>bcc) bcc=b;
203 deg[b]++;
204 }
205 dx=mem[dx].next;
206 }
207 }
208 }
209
210 int main()
211 {
212 read;
213 write;
214 int S,E;
215 while(scanf("%d %d",&N,&M)!=-1)
216 {
217 FORi(1,N+1,1)
218 {
219 G[i].next = -1;
220 }
221 FORi(0,M,1)
222 {
223 scanf("%d %d",&S,&E);
224 Add_edge(2*i+0,S,E);
225 Add_edge(2*i+1,E,S);
226 }
227 Init();
228 memset(used,0,sizeof(used));
229 memset(dfn,0,sizeof(dfn));
230 memset(low,0,sizeof(low));
231 cnt=1;
232 //printf("begin\n");
233 FORi(1,N+1,1)
234 {
235 if(!used[i])
236 {
237 Edge_Bcc_Tarjan(i,-1);
238 }
239 }
240 //printf("end\n");
241 int bcc = -1,ans=0;
242 memset(deg,0,sizeof(deg));
243 Shrink(bcc);
244 FORi(1,bcc+1,1)
245 {
246 if(deg[i]==1)
247 ans++;
248 }
249 printf("%d\n",(ans+1)/2);
250 }
251 return 0;
252 }
posted @ 2011-03-11 16:50  AC2012  阅读(735)  评论(1编辑  收藏  举报