分层最短路-2018南京网赛L

大概题意:

题意:N个点,M条带权有向边,求将K条边权值变为0的情况下,从点1到点N的最短路。

拓展:可以改变K条边的权值为x

做法:把每个点拆成k个点,分别表示还能使用多少次机会,构造新图。

实际写的时候,不用真的拆点,用dist[i][j]表示从源点出发到点i,免费j条边的最小花费,在dijkstra中维护分层即可,每个节点要存价值,编号,已经用的免费条数。

  1 #include <iostream>
  2 #include <queue>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <algorithm>
  7 
  8 using namespace std;
  9 
 10 const int maxm = 200010;  //±ß
 11 const int maxn = 100010; //µã
 12 const int inf = 0x3f3f3f3f;
 13 
 14 struct Edge
 15 {
 16     int to,v,next;
 17 } edge[maxm];
 18 struct node
 19 {
 20     long long val;
 21     int num, h;
 22     node(long long _val=0, int _num=0, int _d=0):val(_val), num(_num),h(_d) {}
 23     bool operator <(const node &tmp) const
 24     {
 25         return val > tmp.val;
 26     }
 27 };
 28 int head[maxn];
 29 int top;
 30 int N, M, K;
 31 long long dis[maxn][15];
 32 bool vis[maxn][15];
 33 long long ans = inf;
 34 void init()
 35 {
 36     memset(head, -1, sizeof(head));
 37     top = 0;
 38     for(int i=0; i<=N; i++)
 39     {
 40         for(int j=0; j<=K; j++)
 41         {
 42             dis[i][j] = inf;
 43             vis[i][j] = false;
 44         }
 45     }
 46     ans = inf;
 47 }
 48 
 49 void addedge(int from, int to, int v)
 50 {
 51     edge[top].to = to;
 52     edge[top].v = v;
 53     edge[top].next = head[from];
 54     head[from] = top++;
 55 }
 56 void dijkstra()
 57 {
 58     priority_queue<node> que;
 59     dis[1][0] = 0;
 60     que.push(node(0, 1, 0));
 61     while(!que.empty())
 62     {
 63         node p = que.top();
 64         que.pop();
 65         int nown = p.num;
 66         int h = p.h;
 67         if(vis[nown][h])
 68             continue;
 69         vis[nown][h] = true;
 70         for(int i=head[nown]; i!=-1; i=edge[i].next)
 71         {
 72             Edge e = edge[i];
 73             if(dis[e.to][h] > dis[nown][h] + e.v)
 74             {
 75                 dis[e.to][h] = dis[nown][h] + e.v;
 76                 que.push(node(dis[e.to][h], e.to, h));
 77             }
 78             //修改的地方
 79             if(dis[e.to][h+1] > dis[nown][h] && h < K)
 80             {
 81                 dis[e.to][h+1] = dis[nown][h];
 82                 que.push(node(dis[nown][h], e.to, h+1));
 83             }
 84         }
 85     }
 86     for(int i=0; i<=K; i++)
 87     {
 88         ans = min(ans, dis[N][i]);
 89     }
 90 }
 91 int main()
 92 {
 93     int T;
 94     scanf("%d",&T);
 95     while(T--)
 96     {
 97         scanf("%d%d%d", &N, &M, &K);
 98         init();
 99         int u, v, c;
100         for(int i=0; i<M; i++)
101         {
102             scanf("%d%d%d", &u, &v, &c);
103             addedge(u, v, c);
104         }
105         dijkstra();
106         printf("%lld\n", ans);
107     }
108     return 0;
109 }

 

posted @ 2018-09-02 13:49  feifei97  阅读(184)  评论(0编辑  收藏  举报