HDU 3488-Tour KM
为什么可以这样拆点在 这道题 都已经证明过
代码:
1 //题目上面说了“The only exception is that the first and the last city should be the same and this city is visited twice.”
2 //我还以为是起点要使用两次,没想到题意就是全部点连接之后出入度都为1
3
4 //题意:有n座城市,m条带权有向边。有人想要游历所有城市,于是制定了计划:游历的路径是一个或者多个环,且所有城市都必须仅存在于一个环中。问怎样设计路线使得总路程最短?
5 //我们可以用最大权匹配去求:
6 //1.对于每个点u,我们拆成u和u'。u代表着出点,在二分图的左侧;u'代表着入点,在二分图的右侧。
7 //2.如果有一条有向边u-->v,那么在二分图中,我们加一条边u-->v',并且权值取反。
8 //
9 //3.利用KM()算法,求出最大权匹配,再将结果取反,即为答案。
10 // 举个三个点的例子
11 // p->q`->q->r`->r->p`
12 //
13 //问:为何KM()算法求出来的就一定是一个或多个环呢?
14 //1.可知,题目已经说明了必定有解。那么对应的二分图必定存在完全匹配,完全匹配也必定是最大匹配。
15 //2.我们用KM()算法求出了最大权匹配。根据性质:最大权匹配必定为最大匹配。所以,如果最大匹配是完全匹配,那么最大权匹配也是完全匹配。
16 //3.因为最大权匹配是完全匹配。所以所求出的解必定是一个或多个环。
17 #include<stdio.h>
18 #include<algorithm>
19 #include<string.h>
20 #include<iostream>
21 #include<queue>
22 #include<vector>
23 using namespace std;
24 const int maxn=510;
25 const int INF=0x3f3f3f3f;
26 int n,m;
27 int g[maxn][maxn],link[maxn],matchx[maxn],matchy[maxn];
28 int slack[maxn],visitx[maxn],visity[maxn];
29 int dfs(int x)
30 {
31 visitx[x]=1;
32 for(int i=1;i<=n;++i)
33 {
34 if(visity[i]) continue;
35 int temp=matchx[x]+matchy[i]-g[x][i];
36 if(temp==0)
37 {
38 visity[i]=1;
39 if(link[i]==-1 || dfs(link[i]))
40 {
41 link[i]=x;
42 return 1;
43 }
44 }
45 else slack[i]=min(slack[i],temp);
46 }
47 return 0;
48 }
49 int km()
50 {
51 memset(link,-1,sizeof(link));
52 memset(matchy,0,sizeof(matchy));
53 for(int i=1;i<=n;++i)
54 {
55 matchx[i]=-INF;
56 for(int j=1;j<=n;++j)
57 {
58 matchx[i]=max(matchx[i],g[i][j]);
59 }
60 }
61 for(int x=1;x<=n;++x)
62 {
63 for(int i=1;i<=n;++i)
64 slack[i]=INF;
65 while(1)
66 {
67 memset(visitx,0,sizeof(visitx));
68 memset(visity,0,sizeof(visity));
69 if(dfs(x)) break;
70 int d=INF;
71 for(int i=1;i<=n;++i)
72 if(!visity[i])
73 d=min(d,slack[i]);
74 for(int i=1;i<=n;++i)
75 {
76 if(visitx[i])
77 matchx[i]-=d;
78 }
79 for(int i=1;i<=n;++i)
80 {
81 if(visity[i]) matchy[i]+=d;
82 else slack[i]-=d;
83 }
84 }
85 }
86 int ans=0;
87 for(int i=1;i<=n;++i)
88 {
89 if(link[i]!=-1)
90 ans+=g[link[i]][i];
91 }
92 return ans;
93 }
94 int main()
95 {
96 int t;
97 scanf("%d",&t);
98 while(t--)
99 {
100 scanf("%d%d",&n,&m);
101 memset(g,0,sizeof(g));
102 for(int i=1;i<=n;++i)
103 {
104 for(int j=1;j<=n;++j)
105 {
106 g[i][j]=-INF;
107 }
108 }
109 while(m--)
110 {
111 int u,v,w;
112 scanf("%d%d%d",&u,&v,&w);
113 g[u][v]=max(-w,g[u][v]);
114 }
115 printf("%d\n",-km());
116 }
117 return 0;
118 }
HDU 3488-Tour KM的更多相关文章
- Hdu 3488 Tour (KM 有向环覆盖)
题目链接: Hdu 3488 Tour 题目描述: 有n个节点,m条有权单向路,要求用一个或者多个环覆盖所有的节点.每个节点只能出现在一个环中,每个环中至少有两个节点.问最小边权花费为多少? 解题思路 ...
- 图论(二分图,KM算法):HDU 3488 Tour
Tour Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- HDU 3488 Tour (最大权完美匹配)【KM算法】
<题目链接> 题目大意:给出n个点m条单向边边以及经过每条边的费用,让你求出走过一个哈密顿环(除起点外,每个点只能走一次)的最小费用.题目保证至少存在一个环满足条件. 解题分析: 因为要求 ...
- HDU - 3488 Tour (KM最优匹配)
题意:对一个带权有向图,将所有点纳入一个或多个环中,且每个点只出现一次,求其所有环的路径之和最小值. 分析:每个点都只出现一次,那么换个思路想,每个点入度出度都为1.将一个点拆成两个点,一个作为入度点 ...
- hdu 3488 Tour
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3488 题意:给你一个N个顶点M条边的带权有向图,要你把该图分成1个或多个不相交的有向环.且所有定点都只 ...
- HDU 3488 Tour(最小费用流:有向环最小权值覆盖)
http://acm.hdu.edu.cn/showproblem.php?pid=3488 题意: 给出n个点和m条边,每条边有距离,把这n个点分成1个或多个环,且每个点只能在一个环中,保证有解. ...
- HDU 3488 KM Tour
参考题解 这题注意有重边.. #include <cstdio> #include <cstring> #include <algorithm> using nam ...
- Tour HDU - 3488 有向环最小权值覆盖 费用流
http://acm.hdu.edu.cn/showproblem.php?pid=3488 给一个无源汇的,带有边权的有向图 让你找出一个最小的哈密顿回路 可以用KM算法写,但是费用流也行 思路 1 ...
- hdu 3488(KM算法||最小费用最大流)
Tour Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- Tour HDU - 3488(最大权值匹配)
Tour In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000) one- ...
随机推荐
- Writing in the science: Introducion
1.what makes a good writing? 2.what makes a good writer? 1) have something to say 2) logical thinkin ...
- Xctf攻防世界—crypto—Normal_RSA
下载压缩包后打开,看到两个文件flag.enc和pubkey.pem,根据文件名我们知道应该是密文及公钥 这里我们使用一款工具进行解密 工具链接:https://github.com/3summer/ ...
- disfunc绕过
绕过DisFunc的常见小技巧 解析webshell命令不能执行时的三大情况 一是 php.ini 中用 disable_functions 指示器禁用了 system().exec() 等等这类命令 ...
- 超详细 安装VMware Workstation,并安装WIN10操作系统连接外网 步骤指导
首先下载VMware Workstation15.1版本,我保存在迅雷链接里面,下载速度非常可观. 链接:https://pan.xunlei.com/s/VMRSt6hHMZXEmPZCm6gJcG ...
- SAP中使用FTP服务
SAP中简单的FTP技术实现基本上如下几个步骤: 1.SM59建立FTP的RFC destination. 可以通过执行SAP的标准程序RSFTP005,自动创建两个名为SAPFTP何SAPFTPA的 ...
- JAVA中@Override的含义
@Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 1.可以当注释用,方便阅读: 2.编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例 ...
- vue中computed/method/watch的区别
摘要:本文通过官方文档结合源码来分析computed/method/watch的区别. Tips:本文分析的源码版本是v2.6.11,文章中牵涉到vue响应式系统原理部分,如果不是很了解,建议先阅读上 ...
- js千分位分隔,数字货币化方法学习记录
js千分位分隔,数字货币化-4种方法(含正则) 方法1-整数货币化 // 整数货币化 function intCurrency(num) { var reg = new RegExp("^[ ...
- SpringBoot单元测试的两种形式
@ 目录 前言 demo环境 springbootTest Junit 总结 前言 最近公司要求2021年所有的项目代码单元测试覆盖率要达到90%,作为刚毕业的小白来说这简直就是噩梦啊,springb ...
- python 字典(formkey 建立 取值 赋值 删除 )
formkey快速建立空字典 result = {}.fromkeys(['name','age','job'],None) print(result) #往字典里添加元素 result. ...