博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu3488——Tour(有向环覆盖,二分图最佳匹配)
阅读量:2343 次
发布时间:2019-05-10

本文共 2796 字,大约阅读时间需要 9 分钟。

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

结论:如果原图能被多个不相交的有向环覆盖,那对应的二分图一定存在最佳匹配。

KM算法是求最佳匹配的最大值,而本题是求最小值,所以要用负权边,另外还要注意有重边

#include 
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#define INF 0x3f3f3f3f#define MAXN 1505#define Mod 10001using namespace std;int pre[MAXN],n,nx,ny,slack[MAXN];int lx[MAXN],ly[MAXN],visx[MAXN],visy[MAXN],map[MAXN][MAXN];int find(int x){ visx[x]=1; for(int y=1; y<=ny; ++y) { if(visy[y]) continue; int tmp=lx[x]+ly[y]-map[x][y]; if(tmp==0) { visy[y]=1; if(pre[y]==-1||find(pre[y])) { pre[y]=x; return 1; } } else if(slack[y]>tmp) slack[y]=tmp; } return 0;}int KM(){ memset(pre,-1,sizeof(pre)); memset(ly,0,sizeof(ly)); for(int i=1; i<=nx; ++i) { lx[i]=-INF; for(int j=1; j<=ny; ++j) if(map[i][j]>lx[i]) lx[i]=map[i][j]; } for(int x=1; x<=nx; ++x) { for(int i=1; i<=ny; ++i) slack[i]=INF; while(1) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(find(x)) break; int d=INF; for(int i=1; i<=ny; ++i) if(!visy[i]&&d>slack[i]) d=slack[i]; for(int i=1; i<=nx; ++i) if(visx[i]) lx[i]-=d; for(int i=1; i<=ny; ++i) if(visy[i]) ly[i]+=d; else slack[i]-=d; } } int res=0; for(int i=1; i<=ny; ++i) if(pre[i]!=0) res+=map[pre[i]][i]; return -res;}int main(){ int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) map[i][j]=-INF; nx=ny=n; while(m--) { int x,y,w; scanf("%d%d%d",&x,&y,&w); map[x][y]=max(map[x][y],-w); } printf("%d\n",KM()); } return 0;}

转载地址:http://qvcvb.baihongyu.com/

你可能感兴趣的文章
Git学习笔记1 神奇的git stash
查看>>
Unable to locate package错误解决办法
查看>>
java项目之——坦克大战09
查看>>
java项目之——坦克大战10
查看>>
java项目之——坦克大战11
查看>>
用sed批量替换文件中的字符
查看>>
九型性格心理测试 (From Ulla Zang荣格的个人性格测验题目)
查看>>
[MT] 3.32升级备忘
查看>>
MT 3.33发布: 安全漏洞修正
查看>>
给Blog加上雅虎通PingMe服务:和网站用户即时聊天
查看>>
顶级域名注册分布统计:2006年09月 .com .de .net .uk .cn
查看>>
雅虎通可以批量添加MSN用户了
查看>>
豆瓣“我上”:一个blog就是一本有趣的书
查看>>
速度比较:GMail/MSN/Yahoo!Mail
查看>>
搜索引擎来路关键词的挖掘:百度统计的高级分析报告导出获取来源关键词
查看>>
C/C++题目--拷贝构造函数概念
查看>>
C/C++题目--深复制与浅复制
查看>>
数据结构教程--李春葆版(总结)之线性表-顺序存储结构练习题
查看>>
linux文件类型
查看>>
alias,which命令
查看>>