题目描述

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 (), 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 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.

输入描述:

* 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

输出描述:

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

示例1

输入
5 5
4 3
4 2
3 2
1 2
2 5

输出
2
说明
Cow 2 loses to cows 1, 3, and 4. Thus, cow 2 is no better than any of the cows 1, 3, and 4. Cow 5 loses to cow 2, so cow 2 is better than cow 5. Thus, cow 2 must be fourth, and cow 5 must be fifth. The ranks of the other cows cannot be determined.

解答

这道题很明显有传递性(即a赢b,b赢c,则a赢c,相反,a输b,b输c,则a输c)
我们设两个型二维数组,其中表示,即的实力比强,表示,即的实力比弱,一边输入,可以一边初始化
输入代码:
n=read();m=read();
for(i=1;i<=m;i++){
    a=read();b=read();
    w[a][b]=true;l[b][a]=true;
}
其中read()为读入优化(听说每500万个数据可省100毫秒)
读入优化代码(需要调用cctype库):
#define g(c) isdigit(c)
#define gc getchar()
int read(){
    char c=0;int x=0,f=0;
    while (!g(c)) f|=c=='-',c=gc;
    while (g(c)) x=x*10+c-48,c=gc;
    return f?-x:x;
}

然后,我们对w和l数组分别进行一次floyd算法(n不大,能过)

floyd算法代码:

void floyd(bool f[N][N]){
    //注意不能写成floyd(bool f[][]),会CE(编译错误)
    for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
    if (i!=k)
    for(int j=1;j<=n;j++)
    if (j!=i&&j!=k)
    f[i][j]=f[i][j]||(f[i][k]&&f[k][j]);
}
//因为floyd算法要进行两遍且两遍代码几乎一样
//所以我们可以把floyd算法定义为一个函数,而非直接打两遍几乎一样的代码
int main(){
    读入+预处理
    floyd(w);floyd(l);
}
最后,我们对于每个,枚举,若,我们把计算器s++,若则答案,输出ans程序结束
因为时,肯定等于(即不可能倒回来又赢),同理时,肯定等于,所以不会出现少算或多算
实际测试中肯定等于,所以不必判断是否相等
for(i=1;i<=n;i++){
    for(j=1,s=0;j<=n;j++)
    if (w[i][j]) s++;
    for(j=1;j<=n;j++)
    if (l[i][j]) s++;
    if (s==n-1) ans++;
}
printf("%d",ans);
完整代码:
#include <bits/stdc++.h>
using namespace std;
const int N=105;
bool w[N][N],l[N][N];
int n,m,a,b,i,j,s,ans;
#define g(c) isdigit(c)
#define gc getchar()
int read(){
    char c=0;int x=0,f=0;
    while (!g(c)) f|=c=='-',c=gc;
    while (g(c)) x=x*10+c-48,c=gc;
    return f?-x:x;
}
void floyd(bool f[N][N]){
    for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
    if (i!=k)
    for(int j=1;j<=n;j++)
    if (j!=i&&j!=k)
    f[i][j]=f[i][j]||(f[i][k]&&f[k][j]);
}
int main(){
//  freopen("t2.in","r",stdin);
    n=read();m=read();
    for(i=1;i<=m;i++){
        a=read();b=read();
        w[a][b]=true;l[b][a]=true;
    }
    //读入+预处理
    floyd(w);floyd(l);
    //floyd算法
    for(i=1;i<=n;i++){
        for(j=1,s=0;j<=n;j++)
        if (w[i][j]) s++;
        for(j=1;j<=n;j++)
        if (l[i][j]) s++;
        if (s==n-1) ans++;
    }
    //计算结果
    printf("%d",ans);
    return 0;
}
最后,说一下万能头bits/stdc++.h
noi比赛文件中说:理论上可以用万能头,但实际中可能不支持使用万能头,若因为使用万能头而导致CE(编译错误),比赛概不负责,即选手负全责!!!
所以,比赛时建议不要使用万能头,平时可以稍微使用一下


来源:少年更应学习,将来为祖国奋斗!