题目链接https://nanti.jisuanke.com/t/31001

题目大意:给出一个含有n个点m条边的带权有向图,求1号顶点到n号顶点的最短路,可以使<=k条任意边的权值变为0。

样例输入 复制

1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2

样例输出 复制

3

解题思路:可以用两种做法,不过都差不多,应该算是同一种思路的不同写法。
第一种是在建图时,将一个点拆成k个层次的点,应该总共有k+1层,每个相同层次的点按输入的边权连接,每个点可以向它能连接到的点的下一个层次连接一条边权为0的边,这样你每使一条边权值变为0,即相当于走到了下一层图,永远不能走回,当走到第k+1层图时即不能使用了,在这个含有k+1层图的大图里跑下最短路就可以得出答案了
附上代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=;
const ll inf=0x3f3f3f3f;
struct qnode{
int u;
ll dis;
bool operator<(const qnode &a)const{
return dis>a.dis;
}
qnode(int a,ll b)
{
u=a;
dis=b;
}
};
struct node{
int v,w,next;
}edge[*maxn];
int n,m,k,tot=,head[maxn];
ll dis[maxn];
void add(int u,int v,int w)
{
edge[tot].v=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
void init()
{
tot=;
memset(head,-,sizeof(head));
}
void dij()
{
priority_queue<qnode> que;
memset(dis,inf,sizeof(dis));
dis[]=;
que.push(qnode(,));
while(!que.empty())
{
int u=que.top().u;
que.pop();
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v,w=edge[i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
que.push(qnode(v,dis[v]));
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
for(int j=;j<=k;j++)
{
add(u+j*n,v+j*n,w); //同一层次的点用输入边权相连
if(j!=k)
add(u+j*n,v+(j+)*n,); //不同层次的点用0权值相连
}
}
if(k>=m)
{
printf("0\n");
continue;
}
ll ans=inf;
dij();
for(int i=;i<=k;i++)
ans=min(ans,dis[n+i*n]);
printf("%lld\n",ans);
}
return ;
}

第二种是用最短路+dp思想,再开一维数组记录已经使用了几次使边的权值为0,也是跑下最短路就可以了。

附上代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+;
const long long inf=0x3f3f3f3f;
struct node{
int v,w,next;
}edge[*maxn];
struct qnode{
int u,k;
long long dis;
bool operator<(const qnode &a)const{
return dis>a.dis;
}
qnode(int a,int b,long long c)
{
u=a;
k=b;
dis=c;
}
};
int n,m,k,tot=,head[maxn];
long long dis[maxn][];
void add(int u,int v,int w)
{
edge[tot].v=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
void init()
{
tot=;
memset(head,-,sizeof(head));
}
long long dijkstra()
{
priority_queue<qnode> que;
for(int i=;i<=n;i++)
{
for(int j=;j<=k;j++)
{
dis[i][j]=inf;
}
}
que.push(qnode(,,));
dis[][]=;
while(!que.empty())
{
int u=que.top().u,tempk=que.top().k;
if(u==n)
return dis[u][tempk];
que.pop();
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v,w=edge[i].w;
if(dis[u][tempk]+w<dis[v][tempk]) //同一层的最短路
{
dis[v][tempk]=dis[u][tempk]+w;
que.push(qnode(v,tempk,dis[v][tempk]));
}
if(tempk<k)
{
if(dis[u][tempk]<dis[v][tempk+]) //如果将这条边权值变为0,就会进入tempk+1层
{
dis[v][tempk+]=dis[u][tempk];
que.push(qnode(v,tempk+,dis[v][tempk+]));
}
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&k);
init();
for(int i=;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
printf("%lld\n",dijkstra());
}
return ;
}

ACM-ICPC 2018 南京赛区网络预赛 L题(分层最短路)的更多相关文章

  1. ACM-ICPC 2018 南京赛区网络预赛 L 【分层图最短路】

    <题目链接> 题目大意: 有N个城市,这些城市之间有M条有向边,每条边有权值,能够选择K条边 边权置为0,求1到N的最短距离. 解题分析: 分层图最短路模板题,将该图看成 K+1 层图,然 ...

  2. ACM-ICPC 2018 南京赛区网络预赛 L题(分层图,堆优化)

    题目链接: https://nanti.jisuanke.com/t/31001 超时代码: #include<bits/stdc++.h> using namespace std; # ...

  3. ACM-ICPC 2018 南京赛区网络预赛 E题

    ACM-ICPC 2018 南京赛区网络预赛 E题 题目链接: https://nanti.jisuanke.com/t/30994 Dlsj is competing in a contest wi ...

  4. ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze

    262144K   There are NN cities in the country, and MM directional roads from uu to v(1\le u, v\le n)v ...

  5. ACM-ICPC 2018 焦作赛区网络预赛 L 题 Poor God Water

    God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells him t ...

  6. ACM-ICPC 2018 南京赛区网络预赛 L.Magical Girl Haze(分层最短路)

    There are N cities in the country, and M directional roads from u to v(1≤u,v≤n). Every road has a di ...

  7. ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze 最短路+分层图

    类似题解 There are NN cities in the country, and MM directional roads from uu to v(1\le u, v\le n)v(1≤u, ...

  8. ACM-ICPC 2018 南京赛区网络预赛 - L Magical Girl Haze (分层迪杰斯特拉)

    题意:N个点,M条带权有向边,求可以免费K条边权值的情况下,从点1到点N的最短路. 分析:K<=10,用dist[i][j]表示从源点出发到点i,免费j条边的最小花费.在迪杰斯特拉的dfs过程中 ...

  9. ACM-ICPC 2018 南京赛区网络预赛 L && BZOJ 2763 分层最短路

    https://nanti.jisuanke.com/t/31001 题意 可以把k条边的权值变为0,求s到t的最短路 解析  分层最短路  我们建立k+1层图 层与层之间边权为0,i 向 i+1层转 ...

随机推荐

  1. C# DataTable详解

    添加引用 using System.Data; 创建表 //创建一个空表 DataTable dt = new DataTable(); //创建一个名为"Table_New"的空 ...

  2. Laravel 门面实例教程 —— 创建自定义 Facades 类

    我们首先创建一个需要绑定到服务容器的Test类: <?php namespace App\Facades; class Test { public function doSomething() ...

  3. Oracle字符函数length substr concat实例

    --字符函数 --伪表dual --(1)求字符串长度 select length('123.456/-*') from dual --(2)截取函数求字符串的子串 ,) from dual --(3 ...

  4. Git本地仓库push至GitHub远程仓库每次输入账户密码问题解决(亲测可行)

    在使用git push命令将本地仓库内容推送至GitHub远程仓库的每一次git都要让我们输入GitHub的用户名和密码.这着实让我们心烦.我们会有疑问,我明明设置了公钥呀!怎么还需要输入账户和密码? ...

  5. Linux基础学习笔记3-用户权限

    本章内容 用户user 令牌token,identity Linux用户:Uername/UID 管理员:root,0 普通用户:1-65535 系统用户:1-499,1-999(Centos7) 对 ...

  6. python中random模块

    random与numpy.random对比: 1.random.random():生成[0,1)之间的随机浮点数: numpy.random.random():生成[0,1)之间的随机浮点数: num ...

  7. ubunto启动chrome报错

    /usr/bin/google-chrome-stable[5199:5199:0703/143543.136117:ERROR:zygote_host_impl_linux.cc(88)] Runn ...

  8. Python cmd库的简易使用

    简单记录一下,竟然这么简单的方法就能在 python 里面实现一个简单的交互式命令行以前从来没有尝试过. 上一个完整的例子: import cmd import osimport readline r ...

  9. kubernetes资源类别介绍

    类别 名称 资源对象 Pod.ReplicaSet.ReplicationController.Deployment.StatefulSet.DaemonSet.Job.CronJob.Horizon ...

  10. 初识Anrdiod SDK

    概念 SDK:(software development kit)软件开发工具包.被软件开发工程师用于为特定的软件包.软件框架.硬件平台.操作系统等建立应用软件的开发工具的集合. 因此,Android ...