传递闭包(例题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 传递闭包———floyd算法

POJ3660:Cow Contest(Floyd传递闭包)

POJ 3660 (Floyd判断传递闭包)

POJ3660-Permutations-传递闭包FLOYD

POJ-3660.Cow Contest(有向图的传递闭包)

Cow Contest POJ - 3660 floyd传递闭包