Hdu 3488 Tour (KM 有向环覆盖)

题目链接:

  Hdu 3488 Tour

题目描述:

  有n个节点,m条有权单向路,要求用一个或者多个环覆盖所有的节点。每个节点只能出现在一个环中,每个环中至少有两个节点。问最小边权花费为多少?

解题思路:

  因为每个节点就出现一个,那么每个节点出度和入度都为1咯。我们可以对每个节点u拆点为u,u‘,分别放在集合X,Y.然后对两个集合进行完备匹配。完备匹配成功以后,每个节点就会有只有一个出度,一个入度的。

用KM求最小匹配的话,先初始化maps为-INF,然后把各边权值存为负,求出最大值取反即可。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn = 310;
 7 const int INF = 0x3f3f3f3f;
 8 int maps[maxn][maxn], used[maxn], s[maxn], n;
 9 int lx[maxn], ly[maxn];
10 bool visx[maxn], visy[maxn];
11 bool Find (int x)
12 {
13     visx[x] = 1;
14     for (int i=1; i<=n; i++)
15     {
16         if (!visy[i] && lx[x]+ly[i]==maps[x][i])
17         {
18             visy[i] = 1;
19             if (!used[i] || Find(used[i]))
20             {
21                 used[i] = x;
22                 return true;
23             }
24         }
25         else
26             s[i] = min (s[i], lx[x] + ly[i] - maps[x][i]);
27     }
28     return false;
29 }
30 int KM ()
31 {
32     memset (used, 0, sizeof(used));
33     memset (lx, 0, sizeof(lx));
34     memset (ly, 0, sizeof(ly));
35     for (int i=1; i<=n; i++)
36         for (int j=1; j<=n; j++)
37             lx[i] = max (lx[i], maps[i][j]);
38     for (int i=1; i<=n; i++)
39     {
40         for (int j=1; j<=n; j++)
41             s[j] = INF;
42         while (1)
43         {
44             memset (visx, 0, sizeof(visx));
45             memset (visy, 0, sizeof(visy));
46             if (Find(i))
47                 break;
48             int d = INF;
49             for (int j=1; j<=n; j++)
50                 if (!visy[j])
51                     d = min (s[j], d);
52             for (int j=1; j<=n; j++)
53             {
54                 if (visx[j])
55                     lx[j] -= d;
56                 if (visy[j])
57                     ly[j] += d;
58             }
59         }
60     }
61     int res = 0;
62     for (int i=1; i<=n; i++)
63         res += maps[used[i]][i];
64     return res;
65 }
66 int main ()
67 {
68     int m, t;
69     scanf ("%d", &t);
70     while (t --)
71     {
72         scanf("%d %d", &n, &m);
73         for (int i=1; i<=n; i++)
74             for (int j=1; j<=n; j++)
75                 maps[i][j] = -INF;
76         while (m --)
77         {
78             int u, v, s;
79             scanf ("%d %d %d", &u, &v, &s);
80             maps[u][v] = max(maps[u][v], -s;
81         }
82         printf ("%d\n", -KM());
83     }
84     return 0;
85 }
时间: 2024-10-23 13:47:45

Hdu 3488 Tour (KM 有向环覆盖)的相关文章

HDU 3488 Tour【多个环的并】

大意:告诉你一些国家和一些单项路,每条路连接两个国家,告诉你之间的距离,现在要使每个国家都在一个环中 求最小距离 分析:这是做过的第二个多个环的并的问题 每个点的入读和出度都为1 把n个点拆点 由于二分图最优匹配的性质可知每个点都会出现在匹配中 相当于每个点出现一次 左边为出度点  有边为入读点 值得注意的是两个国家可能会有多条路 要选取最短的 ----想起东北赛死在这上边了   ----全都是泪啊 代码: 1 #include <iostream> 2 #include <cstdio

HDU 3488 Tour (最大权完美匹配)【KM算法】

<题目链接> 题目大意:给出n个点m条单向边边以及经过每条边的费用,让你求出走过一个哈密顿环(除起点外,每个点只能走一次)的最小费用.题目保证至少存在一个环满足条件. 解题分析: 因为要求包含所有点一次的环,我们不难发现,这个环中的每个点的出度和入度均为1,所以我们不妨将每个点进行拆点,将所有点的出度和入度分为两部分.因为该环需要包括所有的点,并且题目需要求该环的最小权值,相当于该带权二分图的每个点都需要被覆盖到,由于本题就转化为求该二分图的最优完美匹配问题.二分图的最优匹配问题求解,我们会想

HDU 3488 Tour

有向环最小权值覆盖问题 http://blog.csdn.net/u013480600/article/details/39159407 #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; //设置节点数量 const int maxn=4

HDU 1853--Cyclic Tour【最小费用最大流 &amp;&amp; 有向环最小权值覆盖 】

Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1950    Accepted Submission(s): 984 Problem Description There are N cities in our country, and M one-way roads connecting them. Now L

hdu1853/ hdu 3488 有向图,取k个圈覆盖所有点一次//费用流

哎╮(╯▽╰)╭,这是费用流基础题型,拆点,建二分图,跑最小费用最大流即可.若最大流为n,则说明是最大匹配为n,所有点都参与,每个点的入度和出度又是1,所以就是环. 弱菜还需努力! #include<cstdio> #include<iostream> #include<queue> #include<cstring> using namespace std; const int inf=0x3f3f3f3f; int nume=0;int e[50000]

Tour HDU - 3488

Tour HDU - 3488 可以用费用流做 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf = 0x3f3f3f3f; 4 const int maxv = 410; 5 const int maxe = maxv * maxv; 6 7 struct Edge{ 8 int u, v, cap, flow, cost; 9 int nxt; 10 Edge(int u = 0, int v = 0, in

HDU 1853Cyclic Tour(网络流之最小费用流)

题目地址:HDU1853 费用流果然好神奇..还可以用来判断环...如果每个点都是环的一部分而且每个点只能用到一次的话,那每个点的初度入度都是1,这就可以利用网络流来解决,只要拆点令其流量为1,就限制了每个点只能用一次,每次左边的连到右边的,就相当于左边点的一次初度和右边的点的一次入度,很容易想象出来.最后只要判断总流量是否为n即可,因为如果总流量为n的话,说明每个点都出了一次度,每个点都入了一次度,而且由于拆点的流量限制,充分说明了每个点的初度入度都是1.进而说明了每个点都在环里.然后输出最后

有向环覆盖问题

转载自这里 给你一个N个顶点M条边的带权有向图,要你把该图分成一个或多个不相交的有向环.且所有定点都被有向环覆盖.问你该有向环所有权值的总和最小是多少? 答案就是:有向环最大权值覆盖=最优匹配. 分析: 我们把任意一个顶点i都分成两个,即i和i’. 如果原图存在i->j的边,那么二分图有i->j’的边. 下面我们要引出几条结论: ① 如果原图能由多个不相交的有向环覆盖,那么二分图必然存在完备匹配.他们互为充要条件,也就是说如果二分图存在完备匹配,那么原图必定能由几个不想交的有向环覆盖. ② 如

hdoj 3488 Tour 【经典最小费用最大流】

题目:hdoj 3488 Tour 题意:给出n个点m条边,然后让你求每个点只能在一个环中(哈密顿环),且所有点只走一次的最小费用. 分析:直接画图的话可能没有思路,但是把它化成一个二分图的话肯定瞬间思路来了,每个点只走一次,很好建图 建图方案: 每个点拆成两个i 和 ii 然后s连接所有 i ,容量1 ,费用0 ii 连接所有 t ,容量 1 ,费用0 所有右边的点 xi 连接 yii ,费用为权值,容量0 AC代码: #include <cstdlib> #include <ccty