道路翻新 (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\n", t);
100     return 0;
101 }

时间: 2024-08-23 07:52:31

道路翻新 (Revamping Trails, USACO 2009 Feb)的相关文章

BZOJ1579 USACO 2009 Feb Gold 3.Revamping Trails Solution

标题效果:一个N积分m无向图边.它可以是路径k右边缘值变0,确定此时1-n最短路径长度. Sol:我以为我们考虑分层图,图复制k+1部分,每间0~k一层.代表在这个时候已经过去"自由边缘"文章编号. 层与层之间的边权值为0且为单向由上层指向下层. 这样我们以0层的1点做单源最短路径.每一层的n点的距离最小值即为答案. 仅仅只是这种点数为O(K*N),边数为O(K*M),比較慢. 我的做法是,对每一层使用heap-dijkstra算法由本层的原点更新这一层的最短路长度.然后显然能够用O(

BZOJ1577 USACO 2009 Feb Gold 1.Fair Shuttle Solution

权限题,不给传送门啦!在学校OJ上交的.. 有些不开心,又是一道贪心,又是一个高级数据结构的模板,又是看了别人的题解还写崩了QAQ,蒟蒻不需要理由呀. 正经题解: 首先,我们可以由「显然成立法」得出,只要我们按照右端点排序,然后能塞多少就塞多少就一定是最优哒! 你们可以YY一下,如果一堆牛能下车就赶紧下是不是可以得出最优的呢,我感觉不对但是他们都说对 然后就是很基本的线段树维护区间的查询和修改了. 需要注意的一个小地方是如果是线段树修改区间右端点是要-1的,这个很显然. 下面是具体实现: 1 /

【BZOJ】【3398】【USACO 2009 Feb】Bullcow 牡牛和牝牛

组合计数 排列组合求总方案数 这个可以用一个一维的动态规划解决: f[i][0]表示第i头牛是牝牛的方案数 f[i][1]表示第i头牛是牡牛的方案数 则转移为:f[i][0]=f[i-1][0]+f[i-1][1]; f[i][1]=f[i-K-1][0]+f[i-K-1][1]; 常数优化:将取模运算改为if判断语句……可从20ms降为16ms 1 /************************************************************** 2 Problem

[USACO 2009 Feb Gold] Fair Shuttle (贪心+优先队列)

题目大意:有N个站点的轻轨站,有一个容量为C的列车起点在1号站点,终点在N号站点,有K组牛群,每组数量为Mi(1≤Mi≤N),行程起点和终点分别为Si和Ei(1≤Si<Ei≤N).计算最多有多少头牛可以搭乘轻轨. 一道经典的贪心题目,每当一头牛上车的时候,如果超载,我们就优先踢出去行程终点比较远的那部分牛 而 踢出哪些行程终点较远的牛 以及 哪些在车上的牛在这站到达了终点,都可以用优先队列来维护,复杂度约为 贴上代码: 1 #include <cstdio> 2 #include <

【BZOJ 1579】 1579: [Usaco2009 Feb]Revamping Trails 道路升级 (最短路)

1579: [Usaco2009 Feb]Revamping Trails 道路升级 Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N; 1 <= P2_i<= N). John需要T_i (1 <= T_i <= 1,000,000)时间单位用道路i从P1_i走到P2_i或者从P2_i 走

Bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 dijkstra,堆,分层图

1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1573  Solved: 428[Submit][Status][Discuss] Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N;

BZOJ 1579: [Usaco2009 Feb]Revamping Trails 道路升级( 最短路 )

最短路...多加一维表示更新了多少条路 ---------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<iostream> #define rep( i , n ) for( int i

bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 优先队列+dij

1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1768  Solved: 481[Submit][Status][Discuss] Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N;

bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 -- 分层图最短路

1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MB Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N; 1 <= P2_i<= N). John需要T_i (1 <= T_i <