分层最短路-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 }