Mining Station on the Sea

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2997    Accepted Submission(s): 913

Problem Description
The
ocean is a treasure house of resources and the development of human
society comes to depend more and more on it. In order to develop and
utilize marine resources, it is necessary to build mining stations on
the sea. However, due to seabed mineral resources, the radio signal in
the sea is often so weak that not all the mining stations can carry out
direct communication. However communication is indispensable, every two
mining stations must be able to communicate with each other (either
directly or through other one or more mining stations). To meet the need
of transporting the exploited resources up to the land to get put into
use, there build n ports correspondently along the coast and every port
can communicate with one or more mining stations directly.

Due to
the fact that some mining stations can not communicate with each other
directly, for the safety of the navigation for ships, ships are only
allowed to sail between mining stations which can communicate with each
other directly.

The mining is arduous and people do this job
need proper rest (that is, to allow the ship to return to the port). But
what a coincidence! This time, n vessels for mining take their turns to
take a rest at the same time. They are scattered in different stations
and now they have to go back to the port, in addition, a port can only
accommodate one vessel. Now all the vessels will start to return, how to
choose their navigation routes to make the total sum of their sailing
routes minimal.

Notice that once the ship entered the port, it will not come out!

 
Input
There
are several test cases. Every test case begins with four integers in
one line, n (1 = <n <= 100), m (n <= m <= 200), k and p. n
indicates n vessels and n ports, m indicates m mining stations, k
indicates k edges, each edge corresponding to the link between a mining
station and another one, p indicates p edges, each edge indicating the
link between a port and a mining station. The following line is n
integers, each one indicating one station that one vessel belongs to.
Then there follows k lines, each line including 3 integers a, b and c,
indicating the fact that there exists direct communication between
mining stations a and b and the distance between them is c. Finally,
there follows another p lines, each line including 3 integers d, e and
f, indicating the fact that there exists direct communication between
port d and mining station e and the distance between them is f. In
addition, mining stations are represented by numbers from 1 to m, and
ports 1 to n. Input is terminated by end of file.

 
Output
Each test case outputs the minimal total sum of their sailing routes.
 
Sample Input
3 5 5 6
1 2 4
1 3 3
1 4 4
1 5 5
2 5 3
2 4 3
1 1 5
1 5 3
2 5 3
2 4 6
3 1 4
3 2 2
 
Sample Output
13
 

题意:现在有m个油井和n个港口(n<=m),现在有n条船停在这些油井这里,第一行输入n个数, 输入IDX[i]代表第i条船停在 IDX[i]这个油井这里,然后接下来有k行,输入u,v,w代表油井u和油井v之间的距离为w,然后又p行,代表了港口和油井之间的距离,现在这些船全部要回到港口,而且每个港口只能停一艘船,问这些船返回港口的最短距离。

题解:开始的时候建边,要为油田和油田建双向边,但是油田港口只能建单向边,因为回去了就不能往回走了.用spfa求出每艘船到每个港口的距离(注意编号,港口编号为 1+m~n+m),然后求出来之后进行KM算法最优匹配即可得到答案。
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <queue>
  4. #include <algorithm>
  5. #include <stdlib.h>
  6. using namespace std;
  7. const int N = ;
  8. const int INF = ;
  9. int lx[N],ly[N];
  10. bool visitx[N],visity[N];
  11. int slack[N];
  12. int match[N];
  13. int graph[N][N];
  14. int idx[N]; ///船所在的油井下标
  15. int n,m,k,p;
  16. bool Hungary(int u)
  17. {
  18. visitx[u] = true;
  19. for(int i=m+; i<=m+n; i++)
  20. {
  21. if(!visity[i])
  22. {
  23. int temp = lx[u]+ly[i]-graph[u][i];
  24. if(temp==)
  25. {
  26. visity[i] = true;
  27. if(match[i]==-||Hungary(match[i]))
  28. {
  29. match[i] = u;
  30. return true;
  31. }
  32. }
  33. else
  34. {
  35. slack[i] = min(slack[i],temp);
  36. }
  37. }
  38. }
  39. return false;
  40. }
  41. void KM()
  42. {
  43. memset(match,-,sizeof(match));
  44. memset(ly,,sizeof(ly));
  45. for(int i=; i<=n; i++) ///定标初始化
  46. {
  47. lx[idx[i]] = -INF;
  48. }
  49. for(int i=; i<=n; i++)
  50. {
  51. for(int j=m+; j<=n+m; j++)
  52. {
  53. lx[idx[i]] = max(lx[idx[i]],graph[idx[i]][j]);
  54. }
  55. }
  56. for(int i=; i<=n; i++)
  57. {
  58. for(int j=m+; j<=m+n; j++) slack[j] = INF;
  59. while(true)
  60. {
  61. memset(visitx,false,sizeof(visitx));
  62. memset(visity,false,sizeof(visity));
  63. if(Hungary(idx[i])) break;
  64. else
  65. {
  66. int temp = INF;
  67. for(int j=+m; j<=n+m; j++)
  68. {
  69. if(!visity[j]) temp = min(temp,slack[j]);
  70. }
  71. for(int j=; j<=n; j++)
  72. {
  73. if(visitx[idx[j]]) lx[idx[j]]-=temp;
  74. }
  75. for(int j=; j<=n+m; j++)
  76. {
  77. if(visity[j]) ly[j]+=temp;
  78. else slack[j]-=temp;
  79. }
  80. }
  81. }
  82. }
  83. }
  84. struct Edge
  85. {
  86. int v,w,next;
  87. } edge[N*N];
  88. int head[N],tot;
  89. void init()
  90. {
  91. memset(head,-,sizeof(head));
  92. tot = ;
  93. }
  94. void addEdge(int u,int v,int w,int &k)
  95. {
  96. edge[k].v = v,edge[k].w = w,edge[k].next = head[u],head[u] = k++;
  97. }
  98. int low[N];
  99. bool vis[N];
  100. void spfa(int s)
  101. {
  102. for(int i=; i<=n+m; i++)
  103. {
  104. low[i] = INF;
  105. vis[i] = false;
  106. }
  107. queue<int> q;
  108. low[s] = ;
  109. q.push(s);
  110. while(!q.empty())
  111. {
  112. int u = q.front();
  113. q.pop();
  114. vis[u] = false;
  115. for(int i=head[u]; i!=-; i=edge[i].next)
  116. {
  117. int v = edge[i].v,w = edge[i].w;
  118. if(low[v]>low[u]+w)
  119. {
  120. low[v] = low[u]+w;
  121. if(!vis[v])
  122. {
  123. vis[v] = true;
  124. q.push(v);
  125. }
  126. }
  127. }
  128. }
  129. for(int i=+m; i<=n+m; i++)
  130. {
  131. if(low[i]!=INF)
  132. {
  133. graph[s][i] = -low[i];
  134. }
  135. }
  136. }
  137. int main()
  138. {
  139. while(scanf("%d%d%d%d",&n,&m,&k,&p)!=EOF)
  140. {
  141. init();
  142. for(int i=; i<=n; i++)
  143. {
  144. scanf("%d",&idx[i]);
  145. }
  146. /**油田 1-m,港口 m+1-m+n*/
  147. for(int i=; i<=k; i++)
  148. {
  149. int u,v,w;
  150. scanf("%d%d%d",&u,&v,&w);
  151. addEdge(u,v,w,tot);
  152. addEdge(v,u,w,tot);
  153. }
  154. for(int i=; i<=p; i++)
  155. {
  156. int u,v,w;
  157. scanf("%d%d%d",&u,&v,&w);
  158. addEdge(v,u+m,w,tot); ///油井向港口添加单向边
  159. }
  160. memset(graph,,sizeof(graph));
  161. for(int i=; i<=n; i++)
  162. {
  163. spfa(idx[i]);
  164. }
  165. KM();
  166. int ans = ;
  167. for(int i=+m; i<=n+m; i++)
  168. {
  169. if(match[i]!=-)
  170. {
  171. ans+=graph[match[i]][i];
  172. }
  173. }
  174. printf("%d\n",-ans);
  175. }
  176. }

hdu 2448(KM算法+SPFA)的更多相关文章

  1. hdu 3488(KM算法||最小费用最大流)

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

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

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

  3. HDU 2255 KM算法 二分图最大权值匹配

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  4. hdu 4862 KM算法 最小K路径覆盖的模型

    http://acm.hdu.edu.cn/showproblem.php?pid=4862 选t<=k次,t条路要经过全部的点一次而且只一次. 建图是问题: 我自己最初就把n*m 个点分别放入 ...

  5. HDU 1533 KM算法(权值最小的最佳匹配)

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

  6. hdu 3435(KM算法最优匹配)

    A new Graph Game Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  7. hdu 1853 KM算法

    #include<stdio.h> #include<math.h> #include<string.h> #define N 200 #define inf 99 ...

  8. Mining Station on the Sea (hdu 2448 SPFA+KM)

    Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  9. hdu 2255 奔小康赚大钱--KM算法模板

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:有N个人跟N个房子,每个人跟房子都有一定的距离,现在要让这N个人全部回到N个房子里面去,要 ...

随机推荐

  1. 2018 BAT最新《前端必考面试题》

    2018 BAT最新<前端必考面试题> 1.Doctype作用? 严格模式与混杂模式如何区分?它们有何意义? (1). 声明位于文档中的最前面,处于 标签之前.告知浏览器的解析器,用什么文 ...

  2. MongoDB插入数据的3种方法

    insert()方法: 下面是在inventory集合中插入一个三个字段的文档: db.inventory.insert( { _id: 10, type: "misc", ite ...

  3. RabbitMQ基础概念(消息、队列、交换机)

    1.消息的确认 RabbitMQ需要对每一条发送的消息进行确认.消费者必须通过AMQP的basic.ack命令显式地向RabbitMQ发送一个确认,或者在订阅到队列的时候就将auto_ack参数设置为 ...

  4. Spring Boot 启动报错 Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 37

    使用命令 java -jar springBoot.jar  启动项目,结果报错如下: Exception at java.lang.String.substring(String.java:) at ...

  5. 整数中1出现的次数(从1到n整数中1出现的次数)

    整数中1出现的次数(从1到n整数中1出现的次数) 题目描述 求出1 ~ 13的整数中1出现的次数,并算出100 ~ 1300的整数中1出现的次数?为此他特别数了一下1 ~ 13中包含1的数字有1.10 ...

  6. IIS---HTTP 错误 500.19 - Internal Server Error 的解决方法

    在验证IIS是否安装成功,测试了一个页面,报500.19错误 感谢:http://www.cnblogs.com/imjustice/archive/2011/04/04/2198116.html 图 ...

  7. linux命令查看服务器的型号、序列号、内存插槽数(转)

    1,查看服务器型号.序列号: dmidecode|grep "System Information" -A9|egrep  "Manufacturer|Product|S ...

  8. 通过gitlabAPI批量创建用户

    上午服务器领导通知我给服务器所有同事添加gitlab账号,服务器总共67个人,这要是一个一个在页面添加,我得累死,是否有其他的办法呢?有问题找google,果然是可以通过gitlab的API批量添加的 ...

  9. jenkins slave agent 当作服务运行

    1. 接上边编辑好文件 2. 双击以上的jnlp文件 3. 点击弹出的窗口File->save as service, 此时如果报错的话很可能是由于没有安装.net(.net2 以上) 4. 保 ...

  10. Spring与MyBatis的整合(山东数漫江湖)

    首先看一下项目结构图: 具体步骤如下: 1.建立JDBC属性文件 jdbc.properties (文件编码修改为 utf-8 ) driver=com.mysql.jdbc.Driver url=j ...