Tour

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

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
 
题意:和hdu 1853题意和解法几乎一样,但是这题我看英文硬是没看懂。。。题意就是n个城市,每个城市都必须在一个环里面并且也只能出现在一个环里面?问最小的花费是多少?
题解:解法一:最小费用最大流:要去重 不然TLE。每个点只能出现一次,那么一个点容量限制为1,然后拆点跑最小费用最大流即可.
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <queue>
  4. #include <algorithm>
  5. using namespace std;
  6. const int INF = ;
  7. const int N = ;
  8. const int M = ;
  9. struct Edge{
  10. int u,v,cap,cost,next;
  11. }edge[M];
  12. int head[N],tot,low[N],pre[N];
  13. int total ;
  14. bool vis[N];
  15. int flag[N][N];
  16. void addEdge(int u,int v,int cap,int cost,int &k){
  17. edge[k].u=u,edge[k].v=v,edge[k].cap = cap,edge[k].cost = cost,edge[k].next = head[u],head[u] = k++;
  18. edge[k].u=v,edge[k].v=u,edge[k].cap = ,edge[k].cost = -cost,edge[k].next = head[v],head[v] = k++;
  19. }
  20. void init(){
  21. memset(head,-,sizeof(head));
  22. tot = ;
  23. }
  24. bool spfa(int s,int t,int n){
  25. memset(vis,false,sizeof(vis));
  26. for(int i=;i<=n;i++){
  27. low[i] = (i==s)?:INF;
  28. pre[i] = -;
  29. }
  30. queue<int> q;
  31. q.push(s);
  32. while(!q.empty()){
  33. int u = q.front();
  34. q.pop();
  35. vis[u] = false;
  36. for(int k=head[u];k!=-;k=edge[k].next){
  37. int v = edge[k].v;
  38. if(edge[k].cap>&&low[v]>low[u]+edge[k].cost){
  39. low[v] = low[u] + edge[k].cost;
  40. pre[v] = k; ///v为终点对应的边
  41. if(!vis[v]){
  42. vis[v] = true;
  43. q.push(v);
  44. }
  45. }
  46. }
  47. }
  48. if(pre[t]==-) return false;
  49. return true;
  50. }
  51. int MCMF(int s,int t,int n){
  52. int mincost = ,minflow,flow=;
  53. while(spfa(s,t,n))
  54. {
  55. minflow=INF+;
  56. for(int i=pre[t];i!=-;i=pre[edge[i].u])
  57. minflow=min(minflow,edge[i].cap);
  58. flow+=minflow;
  59. for(int i=pre[t];i!=-;i=pre[edge[i].u])
  60. {
  61. edge[i].cap-=minflow;
  62. edge[i^].cap+=minflow;
  63. }
  64. mincost+=low[t]*minflow;
  65. }
  66. total=flow;
  67. return mincost;
  68. }
  69. int n,m;
  70. int main(){
  71. int tcase;
  72. scanf("%d",&tcase);
  73. while(tcase--){
  74. init();
  75. scanf("%d%d",&n,&m);
  76. int src = ,des = *n+;
  77. for(int i=;i<=n;i++){
  78. addEdge(src,i,,,tot);
  79. addEdge(i+n,des,,,tot);
  80. }
  81. memset(flag,-,sizeof(flag));
  82. for(int i=;i<=m;i++){ ///去重
  83. int u,v,w;
  84. scanf("%d%d%d",&u,&v,&w);
  85. if(flag[u][v]==-||w<flag[u][v]){
  86. flag[u][v] = w;
  87. }
  88. }
  89. for(int i=;i<=n;i++){
  90. for(int j=;j<=n;j++){
  91. if(flag[i][j]!=-){
  92. addEdge(i,j+n,,flag[i][j],tot);
  93. }
  94. }
  95. }
  96. int mincost = MCMF(src,des,*n+);
  97. if(total!=n) printf("-1\n");
  98. else printf("%d\n",mincost);
  99. }
  100. }

题解二:KM算法,也是将一个点看成两个点,算最优匹配即可.

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

不去重之后还可以很快跑过去的某大牛的模板.

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<string>
  6. #include<algorithm>
  7. #include<cmath>
  8. #include<set>
  9. #include<vector>
  10. #include<map>
  11. #include<queue>
  12. #include<climits>
  13. #include<assert.h>
  14. #include<functional>
  15. using namespace std;
  16. const int maxn=;
  17. const int INF=;
  18. typedef pair<int,int> P;
  19.  
  20. struct edge
  21. {
  22. int to,cap,cost,rev;
  23. edge(int t,int c,int co,int r)
  24. :to(t),cap(c),cost(co),rev(r){}
  25. edge(){}
  26. };
  27.  
  28. int V;//the number of points
  29. vector<edge>G[maxn];
  30. int h[maxn];
  31. int dist[maxn];
  32. int prevv[maxn],preve[maxn];
  33. void add_edge(int from,int to,int cap,int cost)
  34. {
  35. G[from].push_back(edge(to,cap,cost,G[to].size()));
  36. G[to].push_back(edge(from,,-cost,G[from].size()-));
  37. }
  38.  
  39. void clear()
  40. {
  41. for(int i=;i<V;i++) G[i].clear();
  42. }
  43.  
  44. int min_cost_flow(int s,int t,int f)
  45. {
  46. int res=,k=f;
  47. fill(h,h+V,);//如果下标从1开始,就要+1
  48. while(f>)
  49. {
  50. priority_queue<P,vector<P>,greater<P> >que;
  51. fill(dist,dist+V,INF);
  52. dist[s]=;
  53. que.push(P(,s));
  54. while(!que.empty())
  55. {
  56. P cur=que.top();que.pop();
  57. int v=cur.second;
  58. if(dist[v]<cur.first) continue;
  59. for(int i=;i<G[v].size();i++)
  60. {
  61. edge &e=G[v][i];
  62. if(e.cap>&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to])
  63. {
  64. dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
  65. prevv[e.to]=v;
  66. preve[e.to]=i;
  67. que.push(P(dist[e.to],e.to));
  68. }
  69. }
  70. }
  71. if(dist[t]==INF)
  72. {
  73. return -;
  74. }
  75. for(int v=;v<V;v++) h[v]+=dist[v];//从0还是1开始需要结合题目下标从什么开始
  76.  
  77. int d=f;
  78. for(int v=t;v!=s;v=prevv[v])
  79. {
  80. d=min(d,G[prevv[v]][preve[v]].cap);
  81. }
  82. f-=d;
  83. res+=d*h[t];
  84. for(int v=t;v!=s;v=prevv[v])
  85. {
  86. edge &e=G[prevv[v]][preve[v]];
  87. e.cap-=d;
  88. G[v][e.rev].cap+=d;
  89. }
  90. }
  91. return res;
  92. }
  93.  
  94. int n,m;
  95. int main(){
  96. int tcase;
  97. scanf("%d",&tcase);
  98. while(tcase--){
  99. scanf("%d%d",&n,&m);
  100. clear();
  101. V=*n+;
  102. int src = ,des = *n+;
  103. for(int i=;i<=n;i++){
  104. add_edge(src,i,,);
  105. add_edge(i+n,des,,);
  106. }
  107. for(int i=;i<=m;i++){
  108. int u,v,w;
  109. scanf("%d%d%d",&u,&v,&w);
  110. add_edge(u,n+v,,w);
  111. }
  112. int mincost = min_cost_flow(src,des,n);
  113. printf("%d\n",mincost);
  114. }
  115. }

hdu 3488(KM算法||最小费用最大流)的更多相关文章

  1. hdu 3395(KM算法||最小费用最大流(第二种超级巧妙))

    Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  2. 图论算法-最小费用最大流模板【EK;Dinic】

    图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...

  3. hdu 1533 Going Home 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533 On a grid map there are n little men and n house ...

  4. HDU 5988.Coding Contest 最小费用最大流

    Coding Contest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  5. hdu 3667(拆边+最小费用最大流)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3667 思路:由于花费的计算方法是a*x*x,因此必须拆边,使得最小费用流模板可用,即变成a*x的形式. ...

  6. HDU–5988-Coding Contest(最小费用最大流变形)

    Coding Contest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  7. POJ 2195 & HDU 1533 Going Home(最小费用最大流)

    这就是一道最小费用最大流问题 最大流就体现到每一个'm'都能找到一个'H',但是要在这个基础上面加一个费用,按照题意费用就是(横坐标之差的绝对值加上纵坐标之差的绝对值) 然后最小费用最大流模板就是再用 ...

  8. hdu 1533 Going Home 最小费用最大流 入门题

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  9. hdoj 3488 Tour 【最小费用最大流】【KM算法】

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submi ...

随机推荐

  1. 四连测Day2

    题目:链接: https://pan.baidu.com/s/1ef_9hGBhczW0B4dz5IUKmw 密码: qgjy T1: hash后直接二分查询即可 #include<iostre ...

  2. JavaScript截取中英文字符串

    有时在显示某段文字的时候,可能会太长,影响我们页面的显示效果.如果仅是英文,那么我们可以用String.substring(start, end)函数就已经够用了.但是通常我们都会遇到既有英文,又有汉 ...

  3. ACM1558两线段相交判断和并查集

    Segment set Problem Description A segment and all segments which are connected with it compose a seg ...

  4. [技巧篇]17.那些年一直再逃避的问题,还债Web阶段!

    四海行唐的一阶段和二阶段的时候,再使用数据的时候总是使用List<Map<String,Object>>的东西,但是胖先生一直不怎么喜欢! 所以我再凌云17的Web阶段的时候, ...

  5. java有关Time类型数据的接收和转换

    一:前言 有关Time的时间其实很少有用到.但是用到就很纠结了,转换和保存,都是烦人的事情,我自己就在这上面吃过一个亏,所以就加载下来吧! 二:内容 (1):被坑的地方 实体类 import java ...

  6. js和jq实现全选反选

    在前端中用到全选反选的案例并不少,在这里呢我就实现这个功能给大家参考参考. 这里呢就先贴上我的html和css代码 <div class="wrap"> <tab ...

  7. 51Nod 1050 循环数组最大子段和 | DP

    Input示例 6 -2 11 -4 13 -5 -2 Output示例 20 分析: 有两种可能,第一种为正常从[1 - n]序列中的最大子字段和:第二种为数组的total_sum - ([1-n] ...

  8. 鸡尾酒排序Cocktail sort

    鸡尾酒排序基于冒泡排序,双向循环 还是看例子吧,给定待排数组[2 3 4 5 1] 第一趟过去时的每一步 第一步迭代,2 < 3不换 [2 3 4 5 1] 第二步迭代,3 < 4不换 [ ...

  9. js高阶函数--判断数据类型、函数胡柯里化;

    一.判断数据类型: 常见的判断有typeof.instanceof. constructor. prototype,先来看typeof: var a = "hello world" ...

  10. py_faster_rcnn识别出来的结果好多红框重叠

    py_faster_rcnn识别出来的结果好多红框重叠, 可以通过调节demo.py中的NMS_THRESH的值进行限制. NMS_THRESH表示非极大值抑制,这个值越小表示要求的红框重叠度越小,0 ...