POJ 3660 Cow Contest(Floyd+传递闭包)

题目链接:http://poj.org/problem?id=3660

       题意是有n头牛,然后有m次操作,每次操作有两个数表示A可以打败B,然后要给这n头牛排名,问可以确定几头牛的名次时确定的。

       对于一头牛的排名我们需要知道有多少头牛(i)能打败我,我又能打败多少头(j),那么当i+j==n-1的时候,这头牛的名次就可以确定了,这里就需要用Floyd传递闭包的算法来实现。其实和Floyd很像,思路就是去记录x牛打败了y牛以后,然后在进行传递闭包的时候,就是去更新有没有i打败k,k又打败j的情况,那么i就间接的打败了j。最后统计i+j==n-1有多少个就好了。


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 105
using namespace std;
int pre[maxn][maxn];
int ans[maxn];
int n,m;

inline int getInt(){
    int w = 0,q = 0;
	char ch = getchar();
	while((ch < '0' || ch > '9') && ch != '-') ch = getchar();
	if(ch == '-') q = 1, ch = getchar();
	while(ch >= '0' && ch <= '9') w = w * 10 + ch - '0', ch = getchar();
	return q ? -w : w;
}

int main()
{
    n = getInt();
    m = getInt();
    memset(pre,0,sizeof(pre));
    memset(ans,0,sizeof(ans));
    while(m--){
        int x,y;
        x = getInt();
        y = getInt();
        pre[x][y] = 1;
    }
    for(int k=1;k<=n;k++){       // Floyd
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(pre[i][k] && pre[k][j]){
                    pre[i][j] = 1;
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            ans[i] += pre[i][j];
            ans[j] += pre[i][j];
        }
    }
    int sum = 0;
    for(int i=1;i<=n;i++){
        if(ans[i] == n - 1) sum++;
    }
    printf("%d\n",sum);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Charles_Zaqdt/article/details/81198622