传递闭包(例题POJ3660)
Posted 冰冻三尺 非一日之寒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了传递闭包(例题POJ3660)相关的知识,希望对你有一定的参考价值。
概念:
传递一种关系,例如 a//b b//c 则 a//c
从已知的初始关系中 推出最后所有对象之间的关系
初始时把所有有关系的标记为1 即a[i][j] = 1
然后用Floyd 推出最后的结果 则有关系的两个对象被标记为1
void Floyd() { for(int k=0; k<=n; ++k) for(int i=0; i<=n; ++i) for(int j=0; j<=n; ++j) a[i][j] = a[i][j] || (a[i][k] && a[k][j]); }
例题:POJ3660
题意:
n个牛打架 初始已知m个打架结果 求最后能确定具体名次的牛 有几个
开始就以为是拓扑排序 然后一想。。并查集?
行吧。。。在最短路专题 就是最短路把。。。
当然这题拓排和并查集也能做 https://blog.csdn.net/u010372095/article/details/45201653 请看大佬博客。。。
解析:
用Floyd确定最后的关系后如果 一个牛打败了x个 被y个打败 且x+y == n-1 则 这个牛的名次则可以确定 想一下是不是呀
那么。。。贴代码了。。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxn = 110; int a[maxn][maxn]; int n,m; void Floyd() { for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) a[i][j] = a[i][j] || (a[i][k] && a[k][j]); } int main() { cin>> n >> m; mem(a,0); for(int i=0; i<m; ++i) { int u, v; cin>> u >> v; a[u][v] = 1; } Floyd(); int res = 0; for(int i=1; i<=n; ++i) { int ans = 0; for(int j=1; j<=n; ++j) { if(a[i][j] || a[j][i]) ans++; } if(ans == n-1) res++; } cout<< res <<endl; return 0; }
以上是关于传递闭包(例题POJ3660)的主要内容,如果未能解决你的问题,请参考以下文章
POJ3660:Cow Contest(Floyd传递闭包)
POJ3660-Permutations-传递闭包FLOYD