2942(2)

1 /*
2 用边来保存点连通分量似乎更好理解
3 */
4
5
6
7 // include file
8 #include <cstdio>
9 #include <cstdlib>
10 #include <cstring>
11 #include <cmath>
12 #include <cctype>
13 #include <ctime>
14
15 #include <iostream>
16 #include <sstream>
17 #include <fstream>
18 #include <iomanip>
19 #include <bitset>
20
21 #include <algorithm>
22 #include <string>
23 #include <vector>
24 #include <queue>
25 #include <set>
26 #include <list>
27 #include <functional>
28
29 using namespace std;
30
31 // typedef
32 typedef long long LL;
33 typedef unsigned long long ULL;
34 typedef __int64 Bint;
35
36 //
37 #define read freopen("in.txt","r",stdin)
38 #define write freopen("out.txt","w",stdout)
39 #define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
40 #define FORj(a,b,c) for(int j=(a);j<(b);j+=c)
41 #define FORk(a,b,c) for(int k=(a);k<(b);k+=c)
42 #define FORp(a,b,c) for(int p=(a);p<(b);p+=c)
43 #define FORii(a,b,c) for(int ii=(a);ii<(b);ii+=c)
44 #define FORjj(a,b,c) for(int jj=(a);jj<(b);jj+=c)
45 #define FORkk(a,b,c) for(int kk=(a);kk<(b);kk+=c)
46
47 #define FF(i,a) for(int i=0;i<(a);i++)
48 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
49
50 #define Z(a) (a<<1)
51 #define Y(a) (a>>1)
52
53 const double eps = 1e-6;
54 const double INFf = 1e10;
55 const int INFi = 1000000000;
56 const double Pi = acos(-1.0);
57
58 template<class T> inline T sqr(T a){return a*a;}
59 template<class T> inline T TMAX(T x,T y)
60 {
61 if(x>y) return x;
62 return y;
63 }
64 template<class T> inline T TMIN(T x,T y)
65 {
66 if(x<y) return x;
67 return y;
68 }
69 template<class T> inline void SWAP(T &x,T &y)
70 {
71 T t = x;
72 x = y;
73 y = t;
74 }
75 template<class T> inline T MMAX(T x,T y,T z)
76 {
77 return TMAX(TMAX(x,y),z);
78 }
79
80
81 // code begin
82 #define MAXN 1010
83 #define MAXM 1000010
84 bool mp[MAXN][MAXN];
85 struct node1
86 {
87 int e;
88 int next;
89 };
90 struct node2
91 {
92 int next;
93 };
94 node1 mem[MAXM];
95 node2 G[MAXN];
96 int N,M;
97
98 int dfn[MAXN]; ///
99 int low[MAXN]; //
100 bool used[MAXN]; //
101 int cnt;
102
103 struct node3
104 {
105 node3(){}
106 node3(int a,int b)
107 {
108 u=a;
109 v=b;
110 }
111 int u,v;
112 };
113 node3 stk[MAXN];
114 int top; // 辅助栈
115 int block[MAXN]; // 存贮快
116 int bsize; //每个块的大小
117
118 bool expll[MAXN]; //判断某个点是否被剔除
119 bool bused[MAXN]; //辅助判断二分图用
120 bool bvist[MAXN];
121 int color[MAXN]; //染色用
122 bool ok;
123
124 void Add_edge(int dx,int a,int b)
125 {
126 mem[dx].e = b;
127 mem[dx].next = G[a].next;
128 G[a].next = dx;
129 }
130
131 void Isbipartial( int st,int co)
132 {
133 if(!ok) return;
134 color[st] = co;
135 bvist[st] = true;
136 int dx = G[st].next;
137 while(dx!=-1)
138 {
139 int v = mem[dx].e;
140 if( bused[v] )
141 {
142 if(!bvist[v])
143 {
144 Isbipartial(v,5-co);
145 if(!ok) return;
146 }
147 else
148 {
149 if(color[v]==color[st])
150 {
151 ok = false;
152 return;
153 }
154 }
155 }
156 dx = mem[dx].next;
157 }
158 }
159
160 void BCC_tarjan(int i,int fa)
161 {
162 dfn[i] = cnt;
163 low[i] = cnt;
164 used[i] = true;
165 cnt ++;
166
167 int dx = G[i].next;
168 while(dx!=-1)
169 {
170 int v = mem[dx].e;
171 if(!used[v])
172 {
173 stk[top++] = node3(i,v);
174 BCC_tarjan(v,i);
175 low[i] = TMIN(low[i],low[v]);
176
177 if(low[v]>=dfn[i])
178 {// 割点
179
180 memset(bused,0,sizeof(bused));
181 memset(color,0,sizeof(color));
182 memset(bvist,0,sizeof(bvist));
183 node3 tp;
184 bsize = 0;
185
186 do
187 {
188 tp = stk[--top];
189 block[bsize++] = tp.u;
190 block[bsize++] = tp.v;
191 bused[tp.u] = true;
192 bused[tp.v] = true;
193 }while(!(tp.u==i&&tp.v==v));
194
195 ok = true;
196 Isbipartial(i,2);
197 if( !ok ) //如果是二分图,那么所有的点都要被剔除了,因为它们形成不了奇圈
198 {
199 FORj(0,bsize,1)
200 expll[block[j]] = true;
201 }
202
203
204 }
205 }
206 else if(v!=fa)
207 {
208 low[i] = TMIN(low[i],dfn[v]);
209 }
210
211 dx = mem[dx].next;
212 }
213
214 }
215
216 int main()
217 {
218 read;
219 write;
220 int dx,a,b;
221 while(scanf("%d %d",&N,&M)!=-1)
222 {
223 if(N+M==0)
224 {
225 break;
226 }
227 dx = 0;
228 memset(mp,0,sizeof(mp));
229 FORi(0,M,1)
230 {
231 scanf("%d %d",&a,&b);
232 mp[a][b] = 1;
233 mp[b][a] = 1;
234 }
235
236 FORi(1,N+1,1)
237 {
238 G[i].next = -1;
239 }
240 // 建立补图
241 FORi(1,N+1,1)
242 {
243 FORj(1,N+1,1)
244 {
245 if(!mp[i][j]&&i!=j)
246 {
247 Add_edge(dx++,i,j);
248 }
249 }
250 }
251
252 //CheckG();
253
254 // 求点连通分量
255 memset(dfn,0,sizeof(dfn));
256 memset(low,0,sizeof(low));
257 memset(used,0,sizeof(used));
258 cnt = 1;
259 top = 0;
260 memset(expll,0,sizeof(expll));
261 FORi(1,N+1,1)
262 {
263 if(!used[i])
264 {
265 BCC_tarjan(i,-1);
266 }
267 }
268
269 //
270 int ans = 0;
271 FORi(1,N+1,1)
272 {
273 if(expll[i])
274 ans++;
275 }
276 printf("%d\n",N-ans);
277 }
278 return 0;
279 }
posted @ 2011-03-14 12:54  AC2012  阅读(175)  评论(0编辑  收藏  举报