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,head[M],flag[M][13];
struct edge
{
    int v,next;ll w;
}e[M<<1];
void init(){
    cnt=0;memset(head,-1,sizeof(head));memset(flag,0,sizeof(flag));
}
void add(int u,int v,ll w){
    e[++cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];
    head[u]=cnt;
}
struct node
{
    int index,level;ll dis;
    bool operator < (const node & k) const{
        return dis>k.dis;
    }
}d[M][13];
void dijkstra(int s){
    for(int i=1;i<=n;i++)
        for(int j=0;j<=k;j++)    d[i][j].dis=inf,d[i][j].index=i,d[i][j].level=j;
    priority_queue<node> q;d[s][0].dis=0;q.push(d[s][0]);
    while(!q.empty()){
        int u=q.top().index,lv=q.top().level;q.pop();
        if(flag[u][lv]) continue;
        flag[u][lv]=1;

        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].v;ll w=e[i].w;
            if(d[v][lv].dis>d[u][lv].dis+w){//同一层的最短路径
                d[v][lv].dis=d[u][lv].dis+w;
                q.push(d[v][lv]);
            }
            if(lv<k&&d[v][lv+1].dis>d[u][lv].dis){//如果这条边不选那么就会多一条边不选,状态转移到了lv+1这一层
                d[v][lv+1].dis=d[u][lv].dis;
                q.push(d[v][lv+1]);
            }
        }

    }
    ll ans=d[n][0].dis;
    for(int i=1;i<=k;i++){
        ans=min(ans,d[n][i].dis);
    }
    printf("%lld\n",ans);
}
int main(){
    scanf("%d",&_);
    while(_--){
        init();
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++){
            int u,v;ll w;
            scanf("%d%d%lld",&u,&v,&w);
            add(u,v,w);
        }
        dijkstra(1);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/LMissher/p/9573256.html

时间: 2024-08-30 08:53:06

2018南京网络赛L的相关文章

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

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

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("

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南京网赛L

大概题意: 题意:N个点,M条带权有向边,求将K条边权值变为0的情况下,从点1到点N的最短路. 拓展:可以改变K条边的权值为x 做法:把每个点拆成k个点,分别表示还能使用多少次机会,构造新图. 实际写的时候,不用真的拆点,用dist[i][j]表示从源点出发到点i,免费j条边的最小花费,在dijkstra中维护分层即可,每个节点要存价值,编号,已经用的免费条数. 1 #include <iostream> 2 #include <queue> 3 #include <cstd

2018ICPC南京网络赛

2018ICPC南京网络赛 A. An Olympian Math Problem 题目描述:求\(\sum_{i=1}^{n} i\times i! \%n\) solution \[(n-1) \times (n-1)! \% n= (n-2)!(n^2-2n+1) \%n =(n-2)!\] \[(n-2+1)\times (n-2)! \% n= (n-3)!(n^2-3n+2) \%n =(n-3)! \times 2\] 以此类推,最终只剩下\(n-1\) 时间复杂度:\(O(1)\

2018 CCPC网络赛

2018 CCPC网络赛 Buy and Resell 题目描述:有一种物品,在\(n\)个地点的价格为\(a_i\),现在一次经过这\(n\)个地点,在每个地点可以买一个这样的物品,也可以卖出一个物品,问最终赚的钱的最大值. solution 用两个堆来维护,一个堆维护已经找到卖家的,一个堆维护还没找到卖家的. 对于第\(i\)个地点,在已经找到卖家的堆里找出卖的钱的最小值,如果最小值小于\(a_i\),则将卖家换成\(i\),然后将原来的卖家放到没找到卖家的那里:如果最小值对于\(a_i\)

2018徐州网络赛H. Ryuji doesn&#39;t want to study

题目链接: https://nanti.jisuanke.com/t/31458 题解: 建立两个树状数组,第一个是,a[1]*n+a[2]*(n-1)....+a[n]*1;第二个是正常的a[1],a[2],a[3]...a[n] #include "bits/stdc++.h" using namespace std; #define ll long long const int MAXN=1e5+10; ll sum[MAXN],ans[MAXN]; ll num[MAXN];