poj3660 Cow Contest(Floyd-Warshall方法求有向图的传递闭包)

poj3660 Cow Contest(Floyd-Warshall方法求有向图的传递闭包)

poj3660

题意: 

有n头牛, 给你m对关系(a, b)表示牛a能打败牛b, 求在给出的这些关系下, 能确定多少牛的排名。

分析:

在这呢先说一下关系闭包:  

关系闭包有三种: 自反闭包(r), 对称闭包(s), 传递闭包(t)。

先画出 R 的关系图,再画出 r(R), s(R), t(R) 的关系图。

poj3660 Cow Contest(Floyd-Warshall方法求有向图的传递闭包)        poj3660 Cow Contest(Floyd-Warshall方法求有向图的传递闭包)       poj3660 Cow Contest(Floyd-Warshall方法求有向图的传递闭包)       poj3660 Cow Contest(Floyd-Warshall方法求有向图的传递闭包)

我们今天用的是传递闭包。   仅作为个人理解 传递闭包: 关系之间具有传递性(例如a> b, b> c, 那么a> c), 在那些已给出的关系基础上, 通过传递性, 把所有可能的关系都找出来。  如上图。

 

这里需要先求一下所有牛之间的传递闭包, 那么我们这题与传递闭包又有什么关系呢。 下面将慢慢解答。 

如果一头牛被x头牛打败,并且可以打败y头牛,如果x+y=n-1,则我们容易知道这头牛的排名就被确定了,所以我们只要将任一头牛,可以打败其他的牛的个数x, 和能打败该牛的牛的个数y求出来,在遍历所有牛判断一下是否满足x+y=n-1,就知道这个牛的排名是否能确定了(而传递闭包,正好将所有能得出关系都求出来了), 再将满足这个条件的牛数目加起来就是所求解。 x可以看成是入度, y是出度。

 

在floyd-warshall(不了解该算法的点这里)求每对顶点间的最短路径算法中,可以通过O(v^3)的方法求出图的传递闭包。可以位每条边赋以权值1,然后运行Floyd-Wareshall。如果从  i  到  j  存在一条路径,则d(i,j)<N,否则d(i,j)=MAX。

 

 一种改进的算法是:由于我们需要的只是判断是否从i到j存在一条通路,所以在Floyd-Wareshall中的动态规划比较中,我们可以把min和+操作改为逻辑or( ||  )和逻辑(&&)也就是将  d[i][j] = min(d[i][j],  d[i][k]+dist[k][j]);    改成    if(d[i][j] == 1 || (d[i][k] == 1 && d[k][j] == 1))   d[i][j] = 1;

设  d(i,j) = 1表示从 i 到 j 存在一条通路 p,且 p 的所有中间节点都在0,1,2,…,k中, 否则d(i,j)=0。我们把边(i,j)加入到E*中当且仅当d(i,j)=1。

#include<iostream>
#include<cstdio>
#include<string.h>
#include<cstring>
#include<vector>
using namespace std;

int n, m, ans, v[110][110];

void floyd()//求图的闭包, 把所有可以确定的关系都求出来
{
    for(int k = 1; k <= n; k++)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                if(v[i][j] == 1 || (v[i][k] == 1 && v[k][j] == 1))
                    v[i][j] = 1;
            }
        }
    }
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        memset(v, 0, sizeof(v));
        for(int i = 1; i <= m; i++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            v[x][y] = 1;
        }
        floyd();

        ans = 0;
        for(int i = 1; i <= n; i++)
        {
            int du = 0;
            for(int j = 1; j <= n; j++)//对于每头牛, 求是否有唯一排名
            {
                if(i == j) continue;
                if(v[i][j] == 1 || v[j][i] == 1)
                    du++;
            }
            if(du == n-1)
                ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/wd-one/p/4545086.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109433.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • rocketmq负载均衡机制_rocketmq topic

    rocketmq负载均衡机制_rocketmq topicProducer发送消息时,会首先获取Topic路由信息(通过本地+注册中心拉取),RocketMQ的架构里有多个Broker服务器,而消息队列也会存在于多个Broker服务器里,所以就需要负载均衡策略来将流量尽可能均匀的打到所有服务器上。本章节就介绍一下RocketMQ中常用的四种负载均衡策略。找到Producer发送消息时选择消息队列的逻辑,在类中定义了方法:进入到方法里:上述代码的类中定义了方法:根据源码可以很清楚地看到,默认策略就是依次选择消息队列进行发送,具体的执行细节如下:如何选一个

    2022年10月13日
    2
  • createthread函数详解_createremotethread

    createthread函数详解_createremotethreadCreateRemoteThread和WriteProcessMemory技术示例程序:WinSpy另一种注入代码到其他进程地址空间的方法是使用WriteProcessMemoryAPI。这次你不用编写一个独立的DLL而是直接复制你的代码到远程进程(WriteProcessMemory)并用CreateRemoteThread执行之。让我们看一下CreateRemoteThread

    2025年11月6日
    4
  • PyCharm下使用 ipython 交互式编程「建议收藏」

    PyCharm下使用 ipython 交互式编程「建议收藏」目的:方便调试,查看中间结果,因为觉得设断点调试相对麻烦。【运行环境:macOS10.13.3,PyCharm 2017.2.4】老手:选中代码行,Alt+Shift+E。或选中,鼠标右键-ExecuteLineinConsole。新手:1、安装ipython之后,查看 PyCharm 设置,确保Console的通用设置UseIPythonifavailable选项打勾。…

    2022年8月25日
    5
  • Python基本语法

    Python基本语法Python基本语法

    2022年4月22日
    30
  • 你真的了解python中的换行以及转义吗?「建议收藏」

    你真的了解python中的换行以及转义吗?「建议收藏」python中的分号在python中默认是以换行来标志一行语句的结束。a="xxxx"print(a)#xxxx这段代码很简单,因为a="xxxx&q

    2022年7月6日
    25
  • Microsoft Visio Pro 2016产品密钥激活成功教程完整免费下载

    Microsoft Visio Pro 2016产品密钥激活成功教程完整免费下载https://blog.csdn.net/jingxiansheng/article/details/75805699

    2022年6月24日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号