傳遞閉包(例題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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM