首页 > ACM题库 > HDU-杭电 > HDU 2739-HOJ-Go Go Gorelians-最短路径-[解题报告]C++
2014
02-14

HDU 2739-HOJ-Go Go Gorelians-最短路径-[解题报告]C++

Go Go Gorelians

问题描述 :

The Gorelians travel through space using warp links. Travel through a warp link is instantaneous, but for safety reasons, an individual can only warp once every 10 hours. Also, the cost of creating a warp link increases directly with the linear distance between the link endpoints.

The Gorelians, being the dominant force in the known universe, are often bored, so they frequently conquer new regions of space in the following manner.

1) The initial invasion force finds a suitable planet and conquers it, establishing a Regional Gorelian Galactic Government, hereafter referred to as the RGGG, that will govern all Gorelian matters in this region of space.

2) When the next planet is conquered, a single warp link is constructed between the new planet and the RGGG planet. Planets connected via warp links in this manner are said to be part of the Regional Gorelian Planetary Network, that is, the RGPN.

3) As additional planets are conquered, each new planet is connected with a single warp link to the nearest planet already in the RGPN, thus keeping the cost of connecting new planets to the network to a minimum. If two or more planets are equidistant from the new planet, the new planet is connected to whichever of them was conquered first.

This causes a problem however. Since planets are conquered in a more-or-less random fashion, after a while, the RGGG will probably not be in an ideal location. Some Gorelians needing to consult with the RGGG might only have to make one or two warps, but others might require dozens—very inconvenient when one considers the 10-hour waiting period between warps.

So, once each Gorelian year, the RGGG analyzes the RGPN and relocates itself to an optimal location. The optimal location is defined as a planet that minimizes the maximum number of warps required to reach the RGGG from any planet in the RGPN. As it turns out, there is always exactly one or two such planets. When there are two, they are always directly adjacent via a warp link, and the RGGG divides itself evenly between the two planets.

Your job is to write a program that finds the optimal planets for the RGGG. For the purposes of this problem, the region of space conquered by the Gorelians is defined as a cube that ranges from (0,0,0) to (1000,1000,1000).

输入:

The input consists of a set of scenarios where the Gorelians conquer a region of space. Each scenario is independent. The first line of the scenario is an integer N that specifies the total number of planets conquered by the Gorelians. The next N lines of the input specify, in the order conquered, the IDs and coordinates of the conquered planets to be added to the RGPN, in the format ID X Y Z. An ID is an integer from 1 to 1000. X, Y, and Z are integers from 0 to 1000. A single space separates the numbers. A value of N = 0 marks the end of the input.

输出:

The input consists of a set of scenarios where the Gorelians conquer a region of space. Each scenario is independent. The first line of the scenario is an integer N that specifies the total number of planets conquered by the Gorelians. The next N lines of the input specify, in the order conquered, the IDs and coordinates of the conquered planets to be added to the RGPN, in the format ID X Y Z. An ID is an integer from 1 to 1000. X, Y, and Z are integers from 0 to 1000. A single space separates the numbers. A value of N = 0 marks the end of the input.

样例输入:

5
1 0 0 0
2 0 0 1
3 0 0 2
4 0 0 3
5 0 0 4
5
1 0 0 0
2 1 1 0
3 3 2 0
4 2 1 0
5 3 0 0
10
21 71 76 4
97 32 5 69
70 33 19 35
3 79 81 8
31 91 17 67
52 31 48 75
48 90 14 4
41 73 2 21
83 74 41 69
26 32 30 24
0

样例输出:

3
2 4
31 97

/*若原图的基图不连通,
 或者存在某个点的入度或出度为 0 则无解。
 统计所有点的入度出度之差 Di, 对于 Di > 0 的点,
 加边(s, i, Di, 0); 对于 Di < 0 的点加边(i, t, -Di,0);
 对原图中的每条边(i, j),
 在网络中加边(i, j, ∞, Dij),Dij 为边(i, j)的权值。
 求一次最小费用流,费用加上原图所有边权和即为结果。
 若进一步要求输出最小权值回路,则对所有流量 fij > 0 的边(i, j),在原图中复制fij 份,这样原图便成为欧拉图,求一次欧拉回路即可。
 */
 #include <iostream>
 #include <cstdio>
 #include <cstring>
 #include <queue>
 #include <algorithm>
 #include <cmath>
 
 using namespace std;
 
 const int maxn = 1e2 + 5;
 const int maxm = 2e4 + 5;
 const int inf = 0x3f3f3f3f;
 
 struct MCMF {
     struct Edge {
         int v, c, w, next;
     }p[maxm << 1];
     int e, head[maxn], dis[maxn], pre[maxn], cnt[maxn], sumFlow, n;
     bool vis[maxn];
     void init(int nt){
         e = 0, n = nt + 1;
         memset(head, -1, sizeof(head[0]) * (n + 2));
     }
     void addEdge(int u, int v, int c, int w){
         p[e].v = v; p[e].c = c; p[e].w = w; p[e].next = head[u]; head[u] = e++;
         swap(u, v);
         p[e].v = v; p[e].c = 0; p[e].w = -w; p[e].next = head[u]; head[u] = e++;
     }
     bool spfa(int S, int T){
         queue <int> q;
         for (int i = 0; i <= n; ++i)
             vis[i] = cnt[i] = 0, pre[i] = -1, dis[i] = inf;
         vis[S] = 1; dis[S] = 0;
         q.push(S);
         while (!q.empty()){
             int u = q.front(); q.pop();
             vis[u] = 0;
             for (int i = head[u]; i + 1; i = p[i].next){
                 int v = p[i].v;
                 if (p[i].c && dis[v] > dis[u] + p[i].w){
                     dis[v] = dis[u] + p[i].w;
                     pre[v] = i;
                     if (!vis[v]){
                         q.push(v);
                         vis[v] = 1;
                         if (++cnt[v] > n) return 0;
                     }
                 }
             }
         }
         return dis[T] != inf;
     }
     int mcmf(int S, int T){
         sumFlow = 0;
         int minFlow = 0, minCost = 0;
         while (spfa(S, T)){
             minFlow = inf + 1;
             for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ])
                 minFlow = min(minFlow, p[i].c);
             sumFlow += minFlow;
             for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ]){
                 p[i].c -= minFlow;
                 p[i ^ 1].c += minFlow;
             }
             minCost += dis[T] * minFlow;
         }
         return minCost;
     }
     int ind[maxn], outd[maxn], ans ;
     bool build(int nt, int mt){
         init(nt);
         memset(ind, 0, sizeof(ind));
         memset(outd, 0, sizeof(outd));
         ans = 0;
         int u, v, c;
         while (mt--){
             scanf("%d%d%d", &u, &v, &c);
             u++, v++;
             addEdge(u, v, inf, c);
             ans += c;
             outd[u]++, ind[v]++;
         }
         for (int i = 1; i <= nt; ++i){
             if (ind[i] == 0 || outd[i] == 0) return false;
         }
         for (int i = 1; i <= nt; ++i){
             if (ind[i] - outd[i] > 0)
                 addEdge(0, i, ind[i] - outd[i], 0);
             else if (ind[i] - outd[i] < 0) 
                 addEdge(i, n, outd[i] - ind[i], 0);
         }
         return true;
     }
     void solve(){
         ans += mcmf(0, n);
         printf("%d\n", ans);
     }
 }my;
 int main(){
     int tcase, n, m;
     scanf("%d", &tcase);
     while (tcase--){
         scanf("%d%d", &n, &m);
         if (!my.build(n, m)){
             printf("-1\n");
             continue;
         }
         my.solve();
     }
     return 0;
 }

 

解题参考:http://www.cnblogs.com/Missa/archive/2013/08/21/3273552.html


  1. 第2题,TCP不支持多播,多播和广播仅应用于UDP。所以B选项是不对的。第2题,TCP不支持多播,多播和广播仅应用于UDP。所以B选项是不对的。