标签:des blog http color io os ar for sp
http://poj.org/problem?id=2942
各种逗。。。。
翻译白书上有;看了白书和网上的标程,学习了。。orz。
强连通分量就是先找出割点,然后用个栈在找出割点前维护子树,最后如果这个是割点那么子树就都是强连通分量,然后本题求的是奇圈,那么就进行黑白染色,判断是否为奇圈即可。将不是奇圈的所有强连通分量的点累计起来即可。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << ‘\t‘; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<‘0‘||c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) r=r*10+c-‘0‘; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }
const int N=1005, M=1000005;
int ihead[N], n, m, cnt, LL[N], FF[N], mp[N][N], tot, s[M<<1], top, vis[N], ok[N], col[N];
struct ED { int from, to, next; } e[M<<1];
void add(int u, int v) {
e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].from=u;
e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; e[cnt].from=v;
}
bool ifind(int u) {
int v;
for(int i=ihead[u]; i; i=e[i].next) if(vis[v=e[i].to]) {
if(col[v]==-1) { col[v]=!col[u]; return ifind(v); }
else if(col[v]==col[u]) return true;
}
return false;
}
void color(int x) {
int y, u=e[x].from;
CC(vis, 0); CC(col, -1); col[u]=0;
do {
y=s[top--];
vis[e[y].from]=vis[e[y].to]=1;
} while(y!=x);
if(ifind(u)) for1(i, 1, n) if(vis[i]) ok[i]=1;
}
void tarjan(int u, int fa) {
FF[u]=LL[u]=++tot;
for(int i=ihead[u]; i; i=e[i].next) if(fa!=e[i].to) {
int v=e[i].to;
if(!FF[v]) {
s[++top]=i; //入栈这里要注意。。不要在上边入栈。。
tarjan(v, u);
if(LL[v]>=FF[u]) color(i);
LL[u]=min(LL[u], LL[v]);
}
else if(LL[u]>FF[v]) s[++top]=i, LL[u]=FF[v]; //入栈这里要注意。。
}
}
int main() {
while(1) {
read(n); read(m); int ans=0;
if(n==0 && m==0) break;
CC(mp, 0); CC(ihead, 0); CC(LL, 0); CC(FF, 0); CC(ok, 0); top=cnt=tot=0;
rep(i, m) {
int u=getint(), v=getint();
mp[u][v]=mp[v][u]=1;
}
for1(i, 1, n) for1(j, i+1, n) if(!mp[i][j]) add(i, j);
for1(i, 1, n) if(!FF[i]) tarjan(i, -1);
for1(i, 1, n) if(!ok[i]) ++ans;
printf("%d\n", ans);
}
return 0;
}
Description
Input
Output
Sample Input
5 5 1 4 1 5 2 5 3 4 4 5 0 0
Sample Output
2
Hint
Source
【POJ】2942 Knights of the Round Table(双连通分量)
标签:des blog http color io os ar for sp
原文地址:http://www.cnblogs.com/iwtwiioi/p/4003394.html