1462. 课程表 IV (folyed传递闭包的应用)

这个题就是folyed传递闭包的应用,当然写一个BFS也可以,

这个传递闭包解决的问题是:给你一些边比如A->B->C,表示的是有了A你才能选B,有了B你才能选C,就是给你一个A,C,问

你A是否是选C的条件

代码:

 

void floyd() {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            for (int k = 1; k <= n; k++) {
                if (s[j][i] && s[i][k])
                    s[j][k] = 1;//这个题就是代表j能走到k 
            }
        }
    }
}

 

 

 

传送门

视频讲解

你总共需要上 n 门课,课程编号依次为 0 到 n-1 。

有的课会有直接的先修课程,比如如果想上课程 0 ,你必须先上课程 1 ,那么会以 [1,0] 数对的形式给出先修课程数对。

给你课程总数 n 和一个直接先修课程数对列表 prerequisite 和一个查询对列表 queries 。

对于每个查询对 queries[i] ,请判断 queries[i][0] 是否是 queries[i][1] 的先修课程。

请返回一个布尔值列表,列表中每个元素依次分别对应 queries 每个查询对的判断结果。

注意:如果课程 a 是课程 b 的先修课程且课程 b 是课程 c 的先修课程,那么课程 a 也是课程 c 的先修课程。

 

示例 1:

 

输入:n = 2, prerequisites = [[1,0]], queries = [[0,1],[1,0]]
输出:[false,true]
解释:课程 0 不是课程 1 的先修课程,但课程 1 是课程 0 的先修课程。
示例 2:

输入:n = 2, prerequisites = [], queries = [[1,0],[0,1]]
输出:[false,false]
解释:没有先修课程对,所以每门课程之间是独立的。
示例 3:

 

输入:n = 3, prerequisites = [[1,2],[1,0],[2,0]], queries = [[1,0],[1,2]]
输出:[true,true]
示例 4:

输入:n = 3, prerequisites = [[1,0],[2,0]], queries = [[0,1],[2,0]]
输出:[false,true]
示例 5:

输入:n = 5, prerequisites = [[0,1],[1,2],[2,3],[3,4]], queries = [[0,4],[4,0],[1,3],[3,0]]
输出:[true,false,true,false]
 

提示:

2 <= n <= 100
0 <= prerequisite.length <= (n * (n - 1) / 2)
0 <= prerequisite[i][0], prerequisite[i][1] < n
prerequisite[i][0] != prerequisite[i][1]
先修课程图中没有环。
先修课程图中没有重复的边。
1 <= queries.length <= 10^4
queries[i][0] != queries[i][1]

 

 

这个题的题意就是说:给你一些课程题u->v,就是你选修了u才能选修v,再在给你一个u1,v1,能你u1是否选择是v1的先决条件

这个题就是一个floyed的传递闭包的应用的裸题

class Solution {
public:
    vector<bool> checkIfPrerequisite(int n, vector<vector<int>>& es, vector<vector<int>>& qs) {
        vector<vector<bool>> d(n, vector<bool>(n));
        for(auto e : es) d[e[0]][e[1]]=true;
        for(int k=0;k<n;k++){
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    if(d[i][k]&&d[k][j]){
                        d[i][j]=true;
                    }
                }
            }
        }
        vector<bool>ans;
        for(auto q: qs) ans.push_back(d[q[0]][q[1]]);
        return ans;
    }
};

还有一个题就是

传送门

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 cow B.

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个人m场比赛,后面m行每行有A B,表示A打败的B,问最后能够确定排名的人数有多少。

思路:判断一个人的排名是否确定,只要他与其余n-1个人的关系确定即可。这里涉及到了传递,如A打败了B,B打败了C,那么A间接打败了C。

这里跟floyd算法的思想是一样的,不同的是,floyd求得是最短路,if里更新的距离,这里是判断关系,不需要距离更新。

我们创建一个数字s,s[i][j]表示i打败了j,具体代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e3+100;
int d[maxn][maxn];
int main(){
    int n,m;
    while(cin>>n>>m){
        memset(d,0,sizeof(d));
        while(m--){
            int a,b;
            cin>>a>>b;
            d[a][b]=1;
        }
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(d[i][k]&&d[k][j]){
                        d[i][j]=1;
                    }
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            int p=0;
            for(int j=1;j<=n;j++){
                if(d[i][j]||d[j][i]){
                    p++;
                }
            }
            if(p==n-1){
                ans++;
            } 
        }
        cout<<ans<<endl;
    }
}

 这个也是一个板子题

http://acm.hdu.edu.cn/showproblem.php?pid=1704

posted @ 2021-05-15 13:23  lipu123  阅读(141)  评论(0)    收藏  举报