您的位置:首页 > 运维架构

poj 2186 Popular Cows

2012-03-21 16:20 417 查看
类型:有向图连通性

题目:有n头牛,m个形式如(A, B)表示牛B受牛A欢迎,求受所有牛欢迎的牛的数量

来源:USACO 2003 Fall

思路:在同一强连通分量中,不同牛之间相互受欢迎,可以将其看做一个点[缩点],构造新图。假设新图连通,如果某个牛受所有其他牛欢迎,则其顶点的出度为0,其他点出度不为0,否则将不存在牛受其他所有牛欢迎。如果新图不连通,则存在多个出度为0的点。所以可以通过判断新图点出度为0的个数是否为1来判断解是否存在,如果存在,输出该强连通分量中的点

// poj 2186 Popular Cows
// ac 676K 79MS
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define MIN(a,b) (a) < (b) ? (a) : (b)
#define clr(a,b) memset(a,b,sizeof(a))
#define FOR(i,a,b) for((i) = (a); (i) < (b); ++i)
#define FORE(i,a,b) for((i) = (a); (i) <= (b); ++i)
#define MAXN 10100
#define MAXM 50100

bool vis[MAXN];
int num, cnt, count_node, kk, m, n, cnt_num;
int top, u[MAXM], v[MAXM], step[MAXN], low[MAXN];
int head[MAXN],belong[MAXN],stack[MAXN];
struct edge{
int v,nxt;
}e[MAXM];

void Tarjan(int u) {
int i, j, v;

step[u] = low[u] = ++num;
stack[++top] = u, vis[u] = true;//in_stack[u] = true;
for(i = head[u]; i != -1; i = e[i].nxt) {
v = e[i].v;
if(!step[v]) {
Tarjan(v);
low[u] = MIN(low[u],low[v]);
}
else if(vis[v])
low[u] = MIN(low[u],step[v]);
}
if(step[u] == low[u]){
cnt_num++;
do{
j = stack[top--];
vis[j] = false;
//			in_stack[j] = false;
belong[j] = cnt_num;
}while(j != u);
}
}

int main() {
int i,j,u, v;

while(scanf("%d %d", &n, &m) != EOF){
clr(head, -1);
clr(step, 0);
clr(belong, 0);
clr(vis, false); //clr(in_stack,false);
top = num = cnt = cnt_num = kk = count_node = 0;
FOR(i, 0, m) {
scanf("%d %d", &u, &v);
e[cnt].v = v;
e[cnt].nxt = head[u];
head[u] = cnt++;
}
FORE(i, 1, n)
if(!step[i])
Tarjan(i);
FORE(i, 1, n)
for(j = head[i]; j != -1; j = e[j].nxt)
if(belong[i] != belong[e[j].v])
vis[belong[i]] = true;
FORE(i, 1, cnt_num)
if(!vis[i]) {
count_node++;
kk = i;
}
//!!!
if(count_node != 1)
printf("0\n");
else{
int ans = 0;
FORE(j, 1, n)
if(belong[j] == kk) ans++;
printf("%d\n",ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: