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 ≤ N; A ≠ 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; } }
这个也是一个板子题