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- ...
随机推荐
- 开源:AspNetCore 应用程序热更新升级工具(全网第一份公开的解决方案)
1:下载.开源.使用教程 下载地址:Github 下载 .其它下载 开源地址:https://github.com/cyq1162/AspNetCoreUpdater 使用教程: 解压AspNetCo ...
- SQLI-LABS复现通关
sql-lab 复现通关(深入学习) less-1 基于错误的单引号字符串 - 正常访问 127.0.0.1/?id=1 - 添加 ' 返回报错信息:You have an error in your ...
- 【Spring】创建一个Spring的入门程序
3.创建一个Spring的入门程序 简单记录 - Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)- Spring的基本应用 Spring与Spring MVC的 ...
- 电子邮箱、邮件地址、网站地址正则表达式!几个有用的RE、regex、regexp!
几个常用的正则表达式! r"\w[-\w\.]*@\w[-\w]*(\.\w[-\w]*)+" 这个是电子邮件地址的. r"<TAG\b[^>]*<(. ...
- 分布式系统:xxl-job改造spring-cloud
目录 改造原因 主要改造思路 调度中心 调度中心 执行器侧 总结 修改后的源码仓库地址:GitHub. : 改造原因 原有的xxl-job使用自己实现的http协议进行注册以及调度等,与目前框架中本身 ...
- 从ReentrantLock源码入手看锁的实现
写这篇确实挺伤脑筋的,是按部就班一行一行读,但是我想这么写估计很多没有接触过的可能就劝退了,很容易出现的一种现象就是看了后面忘了前面,而且很容易看了一行代码就一层层往下钻,这样不仅容易打击看源码的积极 ...
- Arduino 上手实战呼吸灯
前言 这篇稿子比以往的时候来的稍晚了一些,望fans们见谅,那即便如此,最终还是姗姗来迟了,公司新一轮战略性部署,被拖出去孵化新产品,开拓新市场去了,手头精力没有那么多了,另外产品一茬接一茬.韭菜一波 ...
- Netty编解码器(理论部分)
背景知识 在了解Netty编解码之前,先回顾一下JAVA的编解码: 编码(Encode):在java中称之为序列化,把内存中易丢失的数据结构或对象状态转换成另一种可存储(存储到磁盘),可在网络间传输的 ...
- 为了更好的多线程性能,在对象创建或者更新时,若数据大于2047字节则 Python 的 GIL 会被释放。 执行计算密集型任务如压缩或哈希时释放 GIL
hashlib - Secure hashes and message digests - Python 3.8.3 documentation https://docs.python.org/3.8 ...
- 极光推送的设备唯一性标识 RegistrationID
极光推送的设备唯一性标识 RegistrationID 极光推送的设备唯一性标识 RegistrationID | 极光博客 https://blog.jiguang.cn/registrationi ...