1. 程式人生 > >POJ 3660 Cow Contest(Floyd求傳遞閉包(可達矩陣))

POJ 3660 Cow Contest(Floyd求傳遞閉包(可達矩陣))

Cow Contest
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 16341 Accepted: 9146

Description

N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors.

The contest is conducted in several head-to-head rounds, each between two cows. If cow A has a greater skill level than cow B (1 ≤ AN; 1 ≤ BN; AB), then cow A will always beat cow B.

Farmer John is trying to rank the cows by skill level. Given a list the results of M (1 ≤ M ≤ 4,500) two-cow rounds, determine the number of cows whose ranks can be precisely determined from the results. It is guaranteed that the results of the rounds will not be contradictory.

Input

* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Each line contains two space-separated integers that describe the competitors and results (the first integer, A, is the winner) of a single round of competition: A and B

Output

* Line 1: A single integer representing the number of cows whose ranks can be determined
 

Sample Input

5 5
4 3
4 2
3 2
1 2
2 5

Sample Output

2

Source

分析;給你n頭牛,m組關係,每組關係形式為A B,代表A比B厲害
問你根據這些關係可以推出有幾頭牛的名次是確定的 如果一頭牛和其他的所有牛的關係都確定了的話,那麼該牛的名次也是確定的
關係的確定分兩種情況:
比如A和C
1.直接確定 題目直接告訴你了A比C厲害
2.間接確定 題目告訴你A比B厲害,B又比C厲害,那麼我們可以推出A比C厲害 所有我們必須考慮間接確定的情況,其實這種間接確定就是一個傳遞閉包
要求傳遞閉包的話我們必須確定可達矩陣
可達矩陣:G[i][j]=1的話,代表i和j之間是可以到達的(直接或者間接到達) 可達矩陣可以使用floyd演算法確定,雖然Floyd是求最短路的,但是也是可以求傳遞閉包(可達矩陣的)
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
int mon1[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
int mon2[13]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};

int getval()
{
    int ret(0);
    char c;
    while((c=getchar())==' '||c=='\n'||c=='\r');
    ret=c-'0';
    while((c=getchar())!=' '&&c!='\n'&&c!='\r')
        ret=ret*10+c-'0';
    return ret;
}

#define max_v 105
int G[max_v][max_v];
int n,m;

void floyd()//求可達矩陣
{
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    continue;
                if(G[i][k]==1&&G[k][j]==1)
                    G[i][j]=1;
            }
        }
    }
}
int main()
{
    int x,y;
    while(~scanf("%d %d",&n,&m))
    {
        memset(G,0,sizeof(G));
        for(int i=1;i<=m;i++)
        {
            scanf("%d %d",&x,&y);
            G[x][y]=1;
        }
        floyd();
        int sum=0;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            cnt=0;
            for(int j=1;j<=n;j++)
            {
                //printf("%d ",G[i][j]);
                if(G[i][j]||G[j][i])
                    cnt++;
            }
          //  printf("\n");
            if(cnt==n-1)//存在某牛和其他n-1頭牛的關係直接或間接確定,那麼該牛名次確定
                sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}
/*
分析;給你n頭牛,m組關係,每組關係形式為A B,代表A比B厲害
問你根據這些關係可以推出有幾頭牛的名次是確定的

如果一頭牛和其他的所有牛的關係都確定了的話,那麼該牛的名次也是確定的
關係的確定分兩種情況:
比如A和C
1.直接確定 題目直接告訴你了A比C厲害
2.間接確定 題目告訴你A比B厲害,B又比C厲害,那麼我們可以推出A比C厲害

所有我們必須考慮間接確定的情況,其實這種間接確定就是一個傳遞閉包
要求傳遞閉包的話我們必須確定可達矩陣
可達矩陣:G[i][j]=1的話,代表i和j之間是可以到達的(直接或者間接到達)

可達矩陣可以使用floyd演算法確定,雖然Floyd是求最短路的,但是也是可以求傳遞閉包(可達矩陣的)

*/