傳遞閉包(例題POJ3660)
阿新 • • 發佈:2018-06-07
blog set stream 博客 floyd LG ont 有關 csdn
概念:
傳遞一種關系,例如 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)