HDU3488 Tour —— 二分图最大权匹配 KM算法

题目链接:https://vjudge.net/problem/HDU-3488

Tour

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 3720    Accepted Submission(s): 1777

Problem Description

In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000) one-way roads connecting them. You are lucky enough to have a chance to have a tour in the kingdom. The route should be designed as: The route should contain one or more loops. (A loop is a route like: A->B->……->P->A.)
Every city should be just in one route.
A loop should have at least two cities. In one route, each city should be visited just once. (The only exception is that the first and the last city should be the same and this city is visited twice.)
The total distance the N roads you have chosen should be minimized.

Input

An integer T in the first line indicates the number of the test cases.
In each test case, the first line contains two integers N and M, indicating the number of the cities and the one-way roads. Then M lines followed, each line has three integers U, V and W (0 < W <= 10000), indicating that there is a road from U to V, with the distance of W.
It is guaranteed that at least one valid arrangement of the tour is existed.
A blank line is followed after each test case.

Output

For each test case, output a line with exactly one integer, which is the minimum total distance.

Sample Input

1
6 9
1 2 5
2 3 5
3 1 10
3 4 12
4 1 8
4 6 11
5 4 7
5 6 9
6 5 4

Sample Output

42

Source

2010 ACM-ICPC Multi-University Training Contest(6)——Host by BIT

Recommend

zhouzeyong

题解:

代码如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 const int INF = 0x3f3f3f3f;
  5 const LL LNF = 9e18;
  6 const int mod = 1e9+7;
  7 const int MAXN = 2e2+10;
  8
  9 int nx, ny;
 10 int g[MAXN][MAXN];
 11 int linker[MAXN], lx[MAXN], ly[MAXN];
 12 int slack[MAXN];
 13 bool visx[MAXN], visy[MAXN];
 14
 15 bool DFS(int x)
 16 {
 17     visx[x] = true;
 18     for(int y = 1; y<=ny; y++)
 19     {
 20         if(visy[y]) continue;
 21         int tmp = lx[x] + ly[y] - g[x][y];
 22         if(tmp==0)
 23         {
 24             visy[y] = true;
 25             if(linker[y]==-1 || DFS(linker[y]))
 26             {
 27                 linker[y] = x;
 28                 return true;
 29             }
 30         }
 31         else
 32             slack[y] = min(slack[y], tmp);
 33     }
 34     return false;
 35 }
 36
 37 int KM()
 38 {
 39     memset(linker, -1, sizeof(linker));
 40     memset(ly, 0, sizeof(ly));
 41     for(int i = 1; i<=nx; i++)
 42     {
 43         lx[i] = -INF;
 44         for(int j = 1; j<=ny; j++)
 45             lx[i] = max(lx[i], g[i][j]);
 46     }
 47
 48     for(int x = 1; x<=nx; x++)
 49     {
 50         for(int i = 1; i<=ny; i++)
 51             slack[i] = INF;
 52         while(true)
 53         {
 54             memset(visx, 0, sizeof(visx));
 55             memset(visy, 0, sizeof(visy));
 56
 57             if(DFS(x)) break;
 58             int d = INF;
 59             for(int i = 1; i<=ny; i++)
 60                 if(!visy[i])
 61                     d = min(d, slack[i]);
 62
 63             for(int i = 1; i<=nx; i++)
 64                 if(visx[i])
 65                     lx[i] -= d;
 66             for(int i = 1; i<=ny; i++)
 67             {
 68                 if(visy[i]) ly[i] += d;
 69                 else slack[i] -= d;
 70             }
 71         }
 72     }
 73
 74     int res = 0;
 75     for(int i = 1; i<=ny; i++)
 76         if(linker[i]!=-1)
 77             res += g[linker[i]][i];
 78     return res;
 79 }
 80
 81 int main()
 82 {
 83     int T, n, m;
 84     scanf("%d", &T);
 85     while(T--)
 86     {
 87         scanf("%d%d", &n,&m);
 88         nx = ny = n;
 89         memset(g, 0, sizeof(g));
 90         for(int i = 1; i<=nx; i++)
 91             for(int j = 1; j<=ny; j++)
 92                 g[i][j] = -INF;
 93         for(int i = 1; i<=m; i++)
 94         {
 95             int u, v, w;
 96             scanf("%d%d%d", &u, &v, &w);
 97             g[u][v] = max(g[u][v], -w);
 98         }
 99
100         printf("%d\n", -KM());
101     }
102 }

时间: 2024-10-09 20:35:47

HDU3488 Tour —— 二分图最大权匹配 KM算法的相关文章

二分图最大权匹配(KM算法)

#80. 二分图最大权匹配 统计 描述 提交 自定义测试 从前一个和谐的班级,有 $n_l$ 个是男生,有 $n_r$ 个是女生.编号分别为 $1, \dots, n_l$ 和 $1, \dots, n_r$. 有若干个这样的条件:第 $v$ 个男生和第 $u$ 个女生愿意结为配偶,且结为配偶后幸福程度为 $w$. 请问这个班级里幸福程度之和最大是多少? 输入格式 第一行三个正整数,$n_l, n_r, m$. 接下来 $m$ 行,每行三个整数 $v, u, w$ 表示第 $v$ 个男生和第 $

二分图 最大权匹配 km算法

这个算法的本质还是不断的找增广路: KM算法的正确性基于以下定理:若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配. 这个定理是显然的.因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和:如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和.所以相等子图的完备匹配一定是二分图的最大权匹配. (1)可行点标:每个点有一个标号,记lx[i]为X方点i的标号,l

带权二分图的最大权匹配 KM算法模版

带权二分图的最大权匹配 KM算法模版 下面是kuangbin大神的模版,已通过西电oj1048的测试 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<set

POJ 2195 二分图最小权匹配KM算法

本来是打算昨天晚上写的, 昨天网速渣的连CSDN都进不去,没办法 只能现在来写了 先写写对KM算法的理解,KM算法是对每个点设置一个顶标,只有当边长等于两边点的顶标之和的时候才进行增广,这样就能保证得到的一定是最大权匹配. 如果找不到匹配的时候就对交替路中X集合的顶标减少一个d Y集合的顶标增加一个d. 这样两个点都在交替路中的时候x[i]+y[i]的和不边 X在 Y不在的时候x[i]+y[i]减少,可能就会为图增加一对匹配. X不在Y在的时候x[i]+y[i]增加, 原来不在现在依然不在其中.

poj 2195 Going Home 二分图最小权匹配KM算法

题意: 有n个人要回到n间房子里,每间房子只允许一个人,求n个人要走的最小距离和. 分析: 裸的二分图最小权匹配,KM搞之. 代码: //poj 2195 //sep9 #include <iostream> using namespace std; const int maxN=128; char g[maxN][maxN]; int mx[maxN],my[maxN],hx[maxN],hy[maxN]; int w[maxN][maxN]; int lx[maxN],ly[maxN],l

HDU 3722 Card Game(二分图最佳完美匹配+KM算法)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3722 1 /* 2 问题 3 将任意的两个字符串进行匹配,使得匹配后权值和最大 4 5 解题思路 6 将任意的字符串的权值计算出来,使用KM算法即可. 7 */ 8 #include<cstdio> 9 #include<cstring> 10 #include<algorithm> 11 using namespace std; 12 13 const int maxn

hdu 2426 Interesting Housing Problem 最大权匹配KM算法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2426 For any school, it is hard to find a feasible accommodation plan with every student assigned to a suitable apartment while keeping everyone happy, let alone an optimal one. Recently the president of

网络流——二分图最优匹配KM算法

前言 其实这个东西只是为了把网络流的内容凑齐而写的(反正我是没有看到过这样子的字体不知道田忌赛马算不算) 算法过程 我们令左边的点(其实二分图没有什么左右)为女生,右边的点为男生,那么: 为每一个女生定一个心仪值,心仪值为她与男生连边中的最大值 为每一个女生找对象,要求男生的心仪值和女生的心仪值的和为他们的边权(男生的心仪值初始为0真惨) 如果没有找到对象,那么将2过程中的女生的心仪值全部-Min,男生的心仪值全部+Min(这个Min是通过自己算的,就是女生除了之前或当前心仪的男生外最心仪的男生

[ACM] HDU 2255 奔小康赚大钱 (二分图最大权匹配,KM算法)

奔小康赚大钱 Problem Description 传说在遥远的地方有一个很富裕的村落,有一天,村长决定进行制度改革:又一次分配房子. 这但是一件大事,关系到人民的住房问题啊. 村里共同拥有n间房间,刚好有n家老百姓,考虑到每家都要有房住(假设有老百姓没房子住的话.easy引起不安定因素),每家必须分配到一间房子且仅仅能得到一间房子. 还有一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.因为老百姓都比較富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比方有3间房