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- ...
随机推荐
- Docker学习笔记之Dockerfile
Dockerfile的编写格式为<命令><形式参数>,命令不区分大小写,但一般使用大写字母.Docker会依据Dockerfile文件中编写的命令顺序依次执行命令.Docker ...
- .NET 5网络操作的改进
随着.net 5在11月的发布,现在是谈论网络栈中许多改进的好时机.这包括对HTTP.套接字.与网络相关的安全性和其他网络通信的改进.在这篇文章中,我将重点介绍一些版本中更有影响力和更有趣的变化. H ...
- 分别使用 Python 和 Math.Net 调用优化算法
1. Rosenbrock 函数 在数学最优化中,Rosenbrock 函数是一个用来测试最优化算法性能的非凸函数,由Howard Harry Rosenbrock 在 1960 年提出 .也称为 R ...
- kubernets之卷
一 卷的由来以及种类和常用的卷的类型 前面介绍了大部分都是pod的管理以及在集群内部和集群外部如何访问pod,但是我们也了解到,pod是有生命周期的,当pod所在节点下线,或者等其他原因原因导致pod ...
- Java异常处理场景中不同位置的返回值详细解析
Java 异常处理中的返回值在不同位置不同场景下是有一些差别的,这里需要格外注意 具体分以下两种场景: 1 finally语句块没有return语句,即当代码执行到try或者catch语句块中的ret ...
- 使用存储过程在mysql中批量插入数据
一.在mysql数据库中创建一张表test DROP TABLE IF EXISTS `test`; CREATE TABLE `test` ( `id` INT (11), `name` VARCH ...
- Python爬虫:数据分析小能手:JSON库的用法
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写. 给大家推荐一个Python交流的q裙,大家在学习遇到了什么问题都可以进群一起交流,大家 ...
- protoc-gen-validate (PGV)
https://github.com/envoyproxy/protoc-gen-validate This project is currently in alpha. The API should ...
- SSL_ERROR_WANT_READ
``` 47757 2020/05/07 06:36:04 [debug] 19413#19413: *23421 event timer: 11, old: 15581551413, new: 15 ...
- C++ Primer Plus读书笔记(六)分支语句和逻辑运算符
1. 以上均包含在cctype中 1 #include<cctype> 2 //#include<ctype.h> 2.文件操作 (1)头文件 1 #include<fs ...