zoukankan      html  css  js  c++  java
  • HDU 2448 Mining Station on the Sea

    题意:有N艘船和N个港口,M个station。现在N艘船分别处在一些station上。有K条边连接站,有P条边连接港口和站。现在这N艘船都要回到港口,且每个港口只能容纳一艘船。问使这N艘船回到港口行程之和的最小值是多少。

    比较明显的求最小权匹配,用KM。做最短路的时候要注意如果船已经回到港口了,就不能再跑出去了,所以做floyd闭包或其他最短路的时候,松弛的时候不能用港口去松弛一个点对。然后得到各个船所在位置到各个港口的最短路后,把边权赋成负的船到港口的最短路值,然后跑KM就可以了。

      1 #include <cstdio>
      2 #include <vector>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define maxn 105
      6 #define INF 1<<30
      7 using namespace std;
      8 
      9 struct KM{
     10     vector<int> G[maxn];
     11     int W[maxn][maxn],n;
     12     int Lx[maxn],Ly[maxn];
     13     int left[maxn];
     14     bool S[maxn],T[maxn];
     15 
     16     void init(int n)
     17     {
     18         this->n = n;
     19         for(int i = 0;i < n;i++)    G[i].clear();
     20         memset(W,0,sizeof(W));
     21     }
     22 
     23     void add_edge(int u,int v,int w)
     24     {
     25         G[u].push_back(v);
     26         W[u][v] = w;
     27     }
     28 
     29     bool match(int i)
     30     {
     31         S[i] = true;
     32         for(int k = 0;k < G[i].size();k++)
     33         {
     34             int j = G[i][k];
     35             if(Lx[i] + Ly[j] == W[i][j] && !T[j])
     36             {
     37                 T[j] = true;
     38                 if(left[j] == -1 || match(left[j]))
     39                 {
     40                     left[j] = i;
     41                     return true;
     42                 }
     43             }
     44         }
     45         return false;
     46     }
     47     void update()
     48     {
     49         int a = INF;
     50         for(int i = 0;i < n;i++)    if(S[i])
     51             for(int k = 0;k < G[i].size();k++)
     52             {
     53                 int j = G[i][k];    if(!T[j])
     54                 a = min(a,Lx[i] + Ly[j] - W[i][j]);
     55             }
     56         for(int i = 0;i < n;i++)
     57         {
     58             if(S[i])    Lx[i] -= a;
     59             if(T[i])    Ly[i] += a;
     60         }
     61     }
     62 
     63     void solve()
     64     {
     65         for(int i = 0;i < n;i++)
     66         {
     67             Lx[i] = *max_element(W[i],W[i]+n);
     68             left[i] = -1;
     69             Ly[i] = 0;
     70         }
     71         for(int i = 0;i < n;i++)
     72         {
     73             while(1)
     74             {
     75                 for(int j = 0;j < n;j++)    S[j] = T[j] = 0;
     76                 if(match(i))    break;
     77                 else            update();
     78             }
     79         }
     80     }
     81 };
     82 KM solver;
     83 int d[310][310];
     84 int pos[105];
     85 
     86 int main(){
     87     int n,m,k,p;
     88     while(scanf("%d%d%d%d",&n,&m,&k,&p) != EOF){
     89         for(int i = 1;i <= n;i++)   scanf("%d",&pos[i]);
     90 
     91         for(int i = 1;i <= m+n;i++)
     92         for(int j = 1;j <= m+n;j++){
     93             if(i != j)  d[i][j] = -1;
     94             else    d[i][j] = 0;
     95         }
     96 
     97         for(int i = 0;i < k;i++){
     98             int a,b,c;
     99             scanf("%d%d%d",&a,&b,&c);
    100             d[a][b] = d[b][a] = d[a][b] == -1 ? c : min(c,d[a][b]);
    101         }
    102 
    103         for(int i = 0;i < p;i++){
    104             int a,b,c;
    105             scanf("%d%d%d",&a,&b,&c);
    106             d[m+a][b] = d[b][m+a] = d[m+a][b] == -1 ? c : min(c,d[m+a][b]);
    107         }
    108 
    109         for(int k = 1;k <= m;k++)
    110         for(int i = 1;i <= m+n;i++) if(d[i][k] != -1)
    111         for(int j = 1;j <= m+n;j++) if(d[k][j] != -1 && (d[i][j] == -1 || d[i][j] > d[i][k] + d[k][j]))
    112         d[i][j] = d[i][k] + d[k][j];
    113 
    114         solver.init(n);
    115 
    116         for(int i = 1;i <= n;i++)
    117         for(int j = 1;j <= n;j++)
    118         if(d[pos[i]][m+j] != -1)
    119         solver.add_edge(i-1,j-1,-d[pos[i]][m+j]);
    120 
    121         solver.solve();
    122 
    123         int ans = 0;
    124         for(int i = 0;i < n;i++)
    125         ans -= solver.W[solver.left[i]][i];
    126         printf("%d
    ",ans);
    127     }
    128     return 0;
    129 }
    View Code
  • 相关阅读:
    AS将一个项目导入到另一个项目中
    Android Studio出现:Cause: unable to find valid certification path to requested target
    小米手机Toast带app名称
    PopupWindow 点击外部区域无法关闭的问题
    EditText inputType类型整理
    Fragment通过接口回调向父Activity传值
    Android selector一些坑
    Installation failed with message Failed to commit install session 634765663 with command cmd package
    旷视上海研究院机器人方向招聘
    语义SLAM的数据关联和语义定位(四)多目标测量概率模型
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3409154.html
Copyright © 2011-2022 走看看