【C++】ZZ1765- 解题精讲

【Horn Coding Studio】CPP编程专栏

题目

题目描述

最近美团举办了一场编程比赛。在赛场上,参赛者们按1..N依次编号。每位参赛者的编程能力不尽相同,参赛者们的编程能力有明确的排名。 整个比赛被分成了若干轮,每一轮是两名指定编号的选手的对决。如果编号为A的的选手编程能力强于编号为B的选手(1 <= A <= N; 1 <= B <= N; A != B) ,那么在对决中,编号为A的选手总是能胜出。 美团想知道选手们编程能力的具体排名,于是美团找来了选手们所有 M(1 <= M <= 4,500)轮比赛的结果,希望你能根据这些信息,推断出尽可能多的选手的编程能力排名。比赛结果保证不会自相矛盾。

输入

第1行: 2个用空格隔开的整数:N 和 M

第2..M+1行: 每行为2个用空格隔开的整数A、B,描述了参加某一轮比赛的选手的编号,以及结果(编号为A,即为每行的第一个数的选手为胜者)

输出

第1行: 输出1个整数,表示排名可以确定的选手的数目

样例输入 复制

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

样例输出 复制

2

提示

输出说明:

编号为2的选手输给了编号为1、3、4的选手,也就是说他的水平比这3名选手都差。而编号为5的选手又输在了他的手下,也就是说,他的水平比编号为5的选手强一些。于是,编号为2的选手的排名必然为第4,编号为5的选手的水平必然最差。其他3名选手的排名仍无法确定。

来源

一点即通

对于每个美团骑手,将其假设为一个点,假如所有点与它的关系都确定了,那么它的排名也就确定了。什么意思呢?就是,比如1、2可以到3,3可以到4、5,那么无论前面的1、2,还是后面的4、5的排位改变都不关3的事,3始终是排第三,(1-2-3-5-4或者2-1-3-4-5)。所以,我们可以把这题奶牛看成是地图上的n个点,f[i][j]表示第i个点可以到达第j个点,f[i][j]=f[i][k]&&f[k][i]表示为第i个点可以通过第k个点到达第j个点。这就是floyd算法的变形。

编号为2的营员输给了编号为1、3、4的营员,也就是说他的水平比这3名营员都差。而编号为5的营员又输在了他的手下,也就是说,他的水平比编号为5的营员强一些。于是,编号为2的营员的排名必然为第4,编号为5的营员的水平必然最差。其他3名营员的排名仍无法确定。
思路:要确定一个人的名次,只看在他前面多少人,在他后面多少人,若为n-1,则可以确定。

代码

ZZOJ     AC     

LuoguOJ     *没有这道题目

#include <bits/stdc++.h>
using namespace std;
vector<int>e1[111];
vector<int>e2[111];
int ans1[111];
int ans2[111];
bool vis[111];

int dfs1(int x) {
    int siz = e1[x].size ();
    int ans = 0;
    for(int i=0;i<=siz-1;i++) {
        int v = e1[x][i];
        if(vis[v]) continue;
        vis[v]=1;
        ans++;
        ans+=dfs1 (v);
    }
    return ans;
}
 
int dfs2(int x) {
    int siz = e2[x].size ();
    int ans = 0;
    for(int i=0;i<=siz-1;i++){
        int v = e2[x][i];
        if(vis[v]) continue;
        vis[v]=1;
        ans++;
        ans+=dfs2 (v);
    }
    return ans;
}
 
int main () {
    int n,m;
    cin>>n>>m;
    while (m--) {
        int a,b;
        cin>>a>>b;
        e1[a].push_back (b);
        e2[b].push_back (a);
    }
    for(int i=1;i<=n;i++) {
        vis[i]=1;
        ans1[i]=dfs1 (i);
        memset (vis,0, sizeof (vis));
    }
    for(int i=1;i<=n;i++){
        vis[i]=1;
        ans2[i]=dfs2(i);
        memset (vis,0, sizeof (vis));
    }
    int ans = 0;
    for(int i=1;i<=n;i++) {
        if(ans1[i]+ans2[i]==n-1) {
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2022-06-11 22:19  冯子坤  阅读(107)  评论(2编辑  收藏  举报