传递闭包(例题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;
}

猜你喜欢

转载自www.cnblogs.com/WTSRUVF/p/9149510.html