POJ 3660Cow Contest(并查集+拓扑排序)

来源:互联网 发布:获奖证书制作软件 编辑:程序博客网 时间:2024/06/06 14:19
Cow Contest
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 7567 Accepted: 4206

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 ≤ A ≤ N; 1 ≤ B ≤ NA ≠ B), then cow A will always beat cowB.

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 54 34 23 21 22 5

Sample Output

2

Source

题意:有n个牛,编号1~n。现给出m条关系:A B ,说明A比B厉害。现在问有多少个牛能被唯一确定(即这头牛与n-1头牛的关系是唯一确定的)。

解题:一头牛如果能被唯一确定,那么所有的点一定是一个连通块,那么就可能用到并查集 来判断。再接下来就是拓扑排序了。具体看代码。

#include<stdio.h>#include<string.h>const int N = 105;bool mapt[N][N],path[N][N];int n,in[N],father[N];void init(){    for(int i=1;i<=n;i++)    {        father[i]=i; in[i]=0;        for(int j=1;j<=n;j++)         mapt[i][j]=path[i][j]=0;        path[i][i]=1;    }}int findroot(int x){    if(x!=father[x])        father[x]=findroot(father[x]);    return father[x];}void setroot(int x,int y){    x=findroot(x);    y=findroot(y);    father[x]=y;}int tope(){    int a[N],k=0,l=0,ans=0;    for(int i=1;i<=n;i++)    if(in[i]==0)      a[k++]=i;    while(l<k)    {        int s=a[l++];        if(l==k)//只有当一个点时,这个点才有可能被确定        {            int i;            for(i=0;i<k;i++)//前方出现的点,看有没有都直接或介接的指向(都有一条有向路可走到s点)             if(path[s][a[i]]==0)             break;            if(i==k)                ans++;//,printf("%d ",s)//输出可确定的点        }        for(int j=1;j<=n;j++)        if(mapt[s][j])        {            in[j]--;            for(int i=0;i<k;i++)//合并                path[j][a[i]]|=path[s][a[i]];            if(in[j]==0)                a[k++]=j;        }    }    return ans;}int main(){    int a,b,m;    while(scanf("%d%d",&n,&m)>0)    {        init();        while(m--)        {            scanf("%d%d",&a,&b);            setroot(a,b);            if(mapt[a][b]==0)             mapt[a][b]=1,in[b]++;        }        int k=0;        for(int i=1;i<=n;i++)            if(father[i]==i)            k++;        if(k>1)//说明所有的点不是在一个连通块内,所有的点都不能被确定            printf("0\n");        else            printf("%d\n",tope());    }}


0 0
原创粉丝点击