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

Cow Contest

Time Limit: 1000MS   Memory Limit: 65536K
Total 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 5
4 3
4 2
3 2
1 2
2 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());
    }
}
时间: 2024-10-03 00:36:34

POJ 3660Cow Contest(并查集+拓扑排序)的相关文章

HDU 1811:Rank of Tetris(并查集+拓扑排序)

http://acm.hdu.edu.cn/showproblem.php?pid=1811 Rank of Tetris Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球.为了更好的符合那些爱好者的喜好,Lele又想了一个新点子:他将制作一个全球Tetris高手排行榜,定时更新,名堂要比福布斯富豪榜还响.关于如何排名,这个不用说都知道是根据Rating从高到低来排,如果两个人具有相同的Rating,那就按

hdu 1811Rank of Tetris (并查集 + 拓扑排序)

1 /* 2 题意:这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B,小于B. 3 4 现在Lele并不是让你来帮他制作这个高手榜,他只是想知道,根据这些信息是否能够确定出这个高手榜,是的话就输出"OK". 5 否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出&quo

hdu--1811--并查集&amp;&amp;拓扑排序&lt;好题&gt;

做了这题 绝逼 累啊.. mle -- re<stack overflow>--tle--wa---ac 经过这么5步 终于AC了 这题 我觉得可以让你更好地来 理解 拓扑排序的一些细节问题 首先 这题 为什么要用到并查集呢? 因为 会有 A = B这种情况的出现 然后可能再来个 B =C A = D....那么我们就需要将它们全部表示成一个点 那么就是都用一个根结点来表示 然后 这边 是要判断 能不能根据给出的条件 形成一个排列 那么就是个 拓扑问题 根据 > <情况来判断 我觉

Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序

https://codeforces.com/contest/1131/problem/D 题意 给你一个n*m二维偏序表,代表x[i]和y[j]的大小关系,根据表构造大小分别为n,m的x[],y[],使得两个数组中最大的数尽量小 题解 按照偏序表,构造出从小到大的拓扑图 如何解决相等的数的偏序关系? 用并查集缩点后再进行拓扑排序 如何解决最大的数最小? 只需要使得同一层的数相同就行,可以一批处理栈中的元素,对于一批栈中的元素产生的新点,先放进一个容器里,然后等到这批栈清空了,再把这个容器中的点

hdu 1811 Rank of Tetris 【并查集+拓扑排序】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1811 分析: 很明显是道拓扑排序的题,有一点就是处理实力相等的问题: 可以用并查集把实力相等的组成一个集合. 说一下拓扑排序的性质: 1.如果入度为0的点大于1,则排序不唯一 2.如果排序的总数小于给定的数,则存在环路 献上代码: #include<stdio.h> #include<string.h> #include<algorithm> #include<ios

hdoj-1811-Rank of Tetris【并查集+拓扑排序】

Rank of Tetris Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6763 Accepted Submission(s): 1901 Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想了一个新点子

HDU 5222 ——Exploration——————【并查集+拓扑排序判有向环】

Exploration Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 194    Accepted Submission(s): 63 Problem Description Miceren likes exploration and he found a huge labyrinth underground! This la

HDU1811Rank of Tetris(并查集+拓扑排序)

Rank of Tetris Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5683    Accepted Submission(s): 1622 Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想

HDU1811 并查集+拓扑排序

题目大意: 判断是否能根据给定的规则将这一串数字准确排序出来 我们用小的数指向大的数 对于相等的情况下,将二者合并到同一个并查集中,最后抽象出来的图上面的每一个点都应该代表并查集的标号 1 #include <cstdio> 2 #include <cstring> 3 #include <stack> 4 #include <iostream> 5 using namespace std; 6 7 #define N 10005 8 char s[N<