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

原文地址:https://www.cnblogs.com/flyuz/p/9573617.html

时间: 2024-08-30 16:52:57

分层最短路-2018南京网赛L的相关文章

2018南京网络赛L

题意是给一幅图可以把k条边权值变为0,求最短路. 分层图裸题,分层图忘完了啊,还在预流推进那做过几道题,难受. 分层图就是再开一维数组记录额外的状态,这道题可以把k条边权值变为0,那那一维数组j就表示有j条边权值为0,做个dp就好. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int M = 1e5+7; const ll inf = 1e18; int _,n,m,k; int cnt,h

2018icpc南京网络赛-L Magical Girl Haze (分层图最短路)

题意: 有向图,可以把k条路的长度变为0,求1到n的最短路 思路: 将图复制k份,一共k+1层图,对于每一条i→j,都连一条低层的i→高层的j,并且权值为0 即对每一对<i,j,w>,都加边<i,j,w>,<i+n,j+n,w>,<i+2n,j+2n,w>,....,<i+kn,j+kn,w> 同时加“楼梯”<i,j+n,0>,<i+n,j+2n,0>,...,<i+(k-1)n, j+kn> 然后跑一个1~(

ICPC 2018 南京网络赛 J Magical Girl Haze(多层图最短路)

传送门:https://nanti.jisuanke.com/t/A1958 题意:n个点m条边的路,你有k次机会将某条路上的边权变为0,问你最短路径长度 题解:最短路变形,我们需要在常规的最短路上多开 一维,记录,我消耗j次机会时的最短路径长度为多少 代码: /** * ┏┓ ┏┓ * ┏┛┗━━━━━━━┛┗━━━┓ * ┃ ┃ * ┃ ━ ┃ * ┃ > < ┃ * ┃ ┃ * ┃... ⌒ ... ┃ * ┃ ┃ * ┗━┓ ┏━┛ * ┃ ┃ Code is far away fro

计蒜客 2018南京网络赛 I Skr ( 回文树 )

题目链接 题意 : 给出一个由数字组成的字符串.然后要你找出其所有本质不同的回文子串.然后将这些回文子串转化为整数后相加.问你最后的结果是多少.答案模 1e9+7 分析 : 应该可以算是回文树挺裸的题目吧 可惜网络赛的时候不会啊.看着马拉车想半天.卒... 对于每一个节点.记录其转化为整数之后的值 然后在回文串插入字符的时候 不断维护这个信息就行了 其实很好理解.看一下代码就懂了 ( 如果你学过回文树的话... ) 就是多加了变量 val .维护语句 #include<bits/stdc++.h

hdu 5053 (2014上海网赛L题 求立方和)

题目大意:给你L到N的范围,要求你求这个范围内的所有整数的立方和. Sample Input2 //T1 32 5 Sample OutputCase #1: 36Case #2: 224 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # define LL long l

ACM 2018 南京网络赛H题Set解题报告

题目描述 给定\(n\)个数$a_i$,起初第\(i\)个数在第\(i\)个集合.有三种操作(共\(m\)次): 1 $u$ $v$ 将第$u$个数和第$v$个数所在集合合并 2 $u$ 将第$u$个数所在集合所有数加1 3 $u$ $k$ $x$ 问$u$所在集合有多少个数模$2^k$余$x$. 数据范围:\(n,m \le 500000,a_i \le 10^9, 0 \le k \le 30\). 简要题解 显然此题可以用set加启发式合并在\(O(n \log ^2 n)\)时间复杂度解

2018南京网络赛 - Skr 回文树

题意:求本质不同的回文串(大整数)的数字和 由回文树的性质可知贡献只在首次进入某个新节点时产生 那么只需由pos和len算出距离把左边右边删掉再算好base重复\(O(n)\)次即可 位移那段写的略微凌乱.. #include<bits/stdc++.h> #define rep(i,j,k) for(int i=j;i<=k;i++) #define rrep(i,j,k) for(int i=j;i>=k;i--) #define println(a) printf("

计蒜客 31001 - Magical Girl Haze - [最短路][2018ICPC南京网络预赛L题]

题目链接:https://nanti.jisuanke.com/t/31001 题意: 一带权有向图,有 n 个节点编号1~n,m条有向边,现在一人从节点 1 出发,他有最多 k 次机会施展魔法使得某一条边的权变成 0,问他走到节点 n 的最小权值为多少. 题解: 将dist数组和vis数组都扩展一维: dist[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离: vis[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离,这个最短距离是否已经被准确计算

2018南京现场赛K 随机输出

题目链接:http://codeforces.com/gym/101981/attachments n和m太小,空地联通无环,总步数太大,直接随机输出5w个方向 #include<iostream> #include<algorithm> #include<ctime> using namespace std; int t,a,b,c,d,k; int main() { srand((unsigned)time(0)); int n,m; char op,ch[4]={