首页 > 其他分享 >【题解】 对决

【题解】 对决

时间:2024-08-15 08:54:15浏览次数:9  
标签:闭包 个人 题解 传递 Floyd 号弱 对决

题目描述

【题目描述】
    已知n个人(编号为1..n)进行了m轮对决,且给出这m轮对决的结果。
    请根据这m轮对决的结果,计算出可以确定多少人的最终排名。
【输入格式】
    第一行两个整数n,m表示总共有n个人,m场对决.
    以下m行,每行两个整数ai,bi,表示ai号的人战胜了bi号的人.
    其中,1<=n<=100,1<=m<=4500。
【输出格式】
    一个数,表示能够确定名次的人的数量.
【样例】
    输入数据 1
        5 5
        4 3
        4 2
        3 2
        1 2
        2 5
    输出数据 1
        2

思路

该题主要考察:Floyd传递闭包

显而易见,对决结果具有传递性。举个例子,1号比2号强,2号比3号强,那么1号比3号强。
所以,首先用Floyd传递闭包传递出所有人两两之间的强弱关系。

然后对于每个人,一共 \(n\) 个人,除去他自己剩下 \(n - 1\) 个人,只要这 \(n - 1\) 个人与他都有强弱关系,就可以确定他的排名。
拿样例举个例子:2号比1号弱,比3号弱,也比4号弱,又比5号强,所以比2号强的有1号、3号、4号,共3个,比他弱的有5号一个。比他强的和比他弱的正好4个人,所以就可以确定2号的排名。

代码

#include <bits/stdc++.h>
using namespace std;

int n, m;
bool a[105][105]; // a[i][j] 记录 i是否比j强。true 表示 i比j强;false则不一定,需要判断 a[j][i]

// Floyd 传递闭包
void Floyd()
{
    for (int k = 1; k <= n; k ++ )
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= n; j ++ )
                if (a[i][k] && a[k][j]) a[i][j] = 1; // 如果i比k强,k比j强,则i比j强
}

int main()
{
    scanf("%d%d", &n, &m);
    while (m -- )
    {
        int x, y; scanf("%d%d", &x, &y);
        a[x][y] = 1; // 记录 x比y强
    }

    Floyd();

    int ans = 0;
    for (int i = 1; i <= n; i ++ )
    {
        bool flag = true;
        for (int j = 1; j <= n; j ++ )
        {
            if (i == j)  continue; // 比较时除去自己
            if (!a[i][j] && !a[j][i]) // 如果i不比j强,j也不比i强,就代表i与j的强弱关系未知
            {
                flag = false; // 记录 i 的强弱关系并不是全部已知
                break;
            }
        }
        if (flag) ans ++ ;  // 如果 i 的强弱关系全部已知,累加答案
    }
    printf("%d\n", ans);

    return 0;
}

标签:闭包,个人,题解,传递,Floyd,号弱,对决
From: https://www.cnblogs.com/T-hong/p/18360143

相关文章

  • CF1530D Secret Santa 题解
    ProblemSolution每个人初始不会给自己送礼物。如果每人要送礼的人都不一样,答案即为\(n\)。如果有两个或以上的人要送给同一个人礼物,假设有\(x\)个人要给同一个人送礼物,那么必有\(x-1\)个人要更改送礼的人,并将礼物送个\(x-1\)个没有礼物收的人。然而这样送礼物可能会导......
  • Coin Troubles题解(dp,拓扑序)
    CoinTroubles题解(dp,拓扑序)题目链接:https://codeforces.com/problemset/problem/283/C题意:有\(n\)种硬币,每种硬币都有一个价格\(ai\),现在有\(q\)个限制,每个限制会告诉你\((b,c)\),并要求\(b\)种硬币的数量严格大于\(c\)种硬币的数量。现在问你一共有多少种买硬币的方法,使得最后......
  • 【题解】CF - 859C : Pie Rules
    原题传送门题目大意:给定一个长为\(N(1\leqN\leq50)\)的序列,Bob和Alice轮流从序列的最前端进行以下操作之一:取出序列最前端的数,并将其加到自己的分数中;取出序列最前端的数,将其加到对方的分数中,则下一轮可继续操作。两人轮流操作直到序列被取完,分数多的一方获胜。若......
  • 暑期模拟赛题解
    暑期模拟赛题解CSP-J模拟赛2024.7.5CSP-J模拟赛1T1简单二分,判断即可。T2\(60pts\)的状压是好写的。至于\(100pts\),考虑dp状态的合并,由于\(m\)的级别很小,考虑对后\(m\)个数状压,考察满足条件的情况。dp难以优化的时候考察本质相同的状态。T3数据范围显......
  • 【题解】【模拟】——帮贡排序
    【题解】【模拟】——帮贡排序帮贡排序题目背景题目描述输入格式输出格式输入输出样例输入#1输出#1提示1.题意解析1.1.结构体储存信息1.2.输入后调整职务的排序规则1.3.分配职务的方法1.4.职务的映射1.5.输出时的排序规则1.6.主函数2.代码帮贡排序题目背景在......
  • 洛谷P2789 直线交点数 题解
    解题思路考虑将直线分组,每组内直线互相平行,任意两组直线间交点数量等于两组内直线数量乘积。分组操作使用dfs,求出交点数量后加入set去重,输出set大小。时间复杂度O(2NN2)有点鬼畜但是可以通过。实现#include<cstdio>#include<unordered_set>inta[30];std::unordered_set......
  • 题解:CF1551D1 Domino (easy version)
    题解:CF1551D1Domino(easyversion)分析题目中保证\(n\timesm\)为偶数,下面进行分类讨论。情况一如果\(n\)和\(m\)都是偶数,那么可以分割成\(\frac{n}{2}\times\frac{m}{2}\)个\(2\times2\)的方块。根据上图我们发现,只要\(k\)满足\(0\lek\le\frac{n}{2}\time......
  • 题解:CF685A Robbers' watch
    题解:CF685ARobbers'watch感觉这题难点主要在理解题意。题意一天\(n\)个小时,一小时\(m\)分钟,手表用\(7\)进制表示时间(位数未填满补前导零),求问这个手表显示的每一位数字都不一样的时刻数量。分析因为是\(7\)进制,所以每一个数字位只可能出现\(0\sim6\)这\(7\)种......
  • P8776 最长不下降子序列 题解
    Statement最长不下降子序列(LIS),但是有一次机会,让序列中连续\(k\)个数改成同一个数。\(n\le10^5,a_i\le10^6\).Solution记\(f(i)\)为以\(i\)结尾的LIS长度,\(g(i)\)为以\(i\)开始的LIS长度,可预处理.答案一定是\(f(i)+k+g(j)\)这样拼接起来的,其中\(i+k+1\le......
  • (CF 10D)最长公共上升子序列(LCIS)(要求输出序列) - 题解
    最长公共上升子序列(LCIS)原题链接:CodeForces、洛谷时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++256MB,其他语言512MB描述给定两个整数序列,写一个程序求它们的最长上升公共子序列。当以下条件满足的时候,我们将长度\(N\)的序列\(S_1,S_2,...,S_N\)称为长度为\(M......