1. 程式人生 > >傳遞閉包(例題POJ3660)

傳遞閉包(例題POJ3660)

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)