貌似以后数学里会学到,不过还是先水一篇博客吧
传递闭包
传递闭包一般用来解决一类具有传递性的问题。
定义:在交际网络中,给定若干个元素和若干对二元关系,且这些关系具有传递性,通过这些传递性推导出尽量多的元素之间的关系的问题叫做传递闭包。
也就是用已知条件来推出其他所有的可知条件。数独应该就是使用了传递闭包的一个例子。再比如,A>B
,B>C
,通过传递闭包,我们就可以得到A>C
。
将传递闭包问题转化为图论问题。
把元素变成一个点,有关系就连一条边。
最后用Floyd
算法解决两点之间的联通关系。
题目大意:已知一些人的绝对实力关系,让你推出,最后有多少人的绝对实力排名是已知的。
这就是经典的Floyd
传递闭包。
不多说了 看题目和代码:
/*
* @Author: hesorchen
* @Date: 2020-04-14 10:33:26
* @LastEditTime: 2020-05-06 10:21:30
* @Link: https://hesorchen.github.io/
*/
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define endl '\n'
#define PI cos(-1)
#define PB push_back
#define ll long long
#define INF 0x3f3f3f3f
#define mod 1000000009
#define lowbit(abcd) (abcd & (-abcd))
#define fre \
{ \
freopen("in.txt", "r", stdin); \
freopen("out.txt", "w", stdout); \
}
int mp[110][110];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
mp[u][v] = 1; //1代表u>v
mp[v][u] = -1; //-1代表u<v
}
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
//传递闭包
if (mp[i][k] == 1 && mp[k][j] == 1)
{
mp[i][j] = mp[i][k];
mp[j][i] = -mp[i][k];
}
else if (mp[j][k] == -1 && mp[k][i] == -1)
{
mp[i][j] = mp[k][i];
mp[j][i] = -mp[k][i];
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
int sum = 0;
for (int j = 1; j <= n; j++)
if (mp[i][j])
sum++;
if (sum == n - 1)
ans++;
}
cout << ans << endl;
return 0;
}