道路翻新 (Revamping Trails, USACO 2009 Feb)

题意:给定m<=50000的1-n有联通的图,求最多可以使K<=20条边变为0的情况下的最短路是多少。。

思路:简单的分层图最短路,对于每个点拆成K个点。。

        然后求一边最短路。。

code:

  1 /*
  2  * Author:  Yzcstc
  3  * Created Time:  2014/11/5 19:25:47
  4  * File Name: revamp.cpp
  5  */
  6 #include<cstdio>
  7 #include<iostream>
  8 #include<cstring>
  9 #include<cstdlib>
 10 #include<cmath>
 11 #include<algorithm>
 12 #include<string>
 13 #include<map>
 14 #include<set>
 15 #include<vector>
 16 #include<queue>
 17 #include<stack>
 18 #include<ctime>
 19 #define M0(x)  memset(x, 0, sizeof(int) * (n+10))
 20 #define MP make_pair
 21 #define x first
 22 #define y second
 23 using namespace std;
 24 typedef long long ll;
 25 typedef pair<ll, int> pii;
 26 const int maxn = 1200000;
 27 struct edge{
 28     int v, w, next;     
 29 } e[maxn * 5];
 30 int last[maxn], tot;
 31 int n, k, m;
 32 
 33 void add(const int &u,const int &v, const int& w){
 34      e[tot] = (edge){v, w, last[u]}; last[u] = tot++;
 35 }
 36      
 37 void init(){
 38      int u, v, w;
 39      memset(last, -1, sizeof(int) * (n * k + 10));
 40      tot = 0;
 41      for (int i = 0; i < m; ++i){
 42           scanf("%d%d%d", &u, &v, &w);
 43           add(u, v, w); add(v, u, w);
 44           for (int i = 1; i <= k; ++i){
 45                add(u + i * n, v + i * n, w);
 46                add(v + i * n, u + i * n, w); 
 47                add(u + (i-1) * n, v + i * n, 0);
 48                add(v + (i-1) * n, u + i * n, 0);
 49           }
 50      }
 51 }
 52 
 53 ll dis[maxn];
 54 int vis[maxn];
 55 void dij(){
 56      priority_queue<pii, vector<pii>, greater<pii> > q;
 57      int nt = n * k + n;
 58      memset(vis, 0, sizeof(vis));
 59      for (int i = 1; i <= nt; ++i) dis[i] = (1LL<<50); 
 60      pii tmp(0, 1); dis[1] = 0;
 61      q.push(tmp);
 62      int u, v;
 63      while (!q.empty()){
 64           u = q.top().y;
 65           q.pop();
 66           if (vis[u]) continue;
 67           vis[u] = 1;
 68           for (int p = last[u]; ~p; p = e[p].next){
 69                v = e[p].v;
 70                if (dis[u] + e[p].w < dis[v]){
 71                     dis[v] = dis[u] + e[p].w;
 72                     tmp.x = dis[v], tmp.y = v;
 73                     q.push(tmp);         
 74                }    
 75           }            
 76      }
 77 }
 78 
 79 
 80 void solve(){
 81      dij();
 82      ll ans = 1LL<<50;
 83      for (int i = 0; i <= k; ++i)
 84         ans = min(ans, dis[n+i*n]);
 85      cout << ans << endl;
 86 }
 87 
 88 int main(){
 89     freopen("a.in", "r", stdin);
 90     freopen("a.out", "w", stdout);
 91     clock_t start, finish;
 92     start = clock();
 93     while (scanf("%d%d%d", &n, &m, &k) != EOF){
 94          init();
 95          solve();
 96     }
 97     finish = clock();
 98     double t = (double)(finish - start) / CLOCKS_PER_SEC;
 99 //    printf("time = %.6f
", t);
100     return 0;
101 }
View Code
原文地址:https://www.cnblogs.com/yzcstc/p/4077273.html