题解 P1948 【[USACO08JAN]电话线Telephone Lines】
虽然这题题解已经有不少了,但是蒟蒻还是想来一发题解qwq
看了看各路神仙的题解,发现大部分都是spfa+二分的答案
但是本蒟蒻看完题目的第一反应就是
这不就是个分层图最短路吗
直接建图开冲
测一波样例...... 输出5???
原来是没看题的锅,题目给出的计算规则是只花费路线中最长的一条路的价钱,而不是将所有路径长度相加求出k次免费的总的最短路
那只需要把代码改一下就好了
但是蒟蒻本来就不是很会分层图,卡了半天总是出0......
无奈之下只能换dijkstra+dp切了这题
当然还用了堆优化,总的来说这题还是很水的,就是代码比较难以实现(个人观点)
代码还是最直观的,各位神仙可以结合代码进行理解
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;
const int N=100050,M=10005,inf=(1<<30);
int cnt,to[N],nxt[N],w[N],n,T,head[N],m,flag[M][21],d[M][21];
int read()
{
int res=0,kkk=1;char ch=' ';
while(ch<'0'||ch>'9'){
ch=getchar();
if(ch=='-')kkk=-1;
}
while(ch>='0'&&ch<='9'){
res=res*10+ch-'0';
ch=getchar();
}
return res*kkk;
}
struct node{
int x,d,num;
friend bool operator < (node p, node q){
return p.d > q.d;
}
};
void addedge(int x,int y,int dis)
{
to[++cnt]=y;
w[cnt]=dis;
nxt[cnt]=head[x];
head[x]=cnt;
}
void add(int x,int y,int z)
{
addedge(x,y,z);
addedge(y,x,z);
}
priority_queue <node> q;
void dijkstra()
{
for(int i=1;i<=n;i++){
for(int j=0;j<=T;j++)
d[i][j]=inf;
}
d[1][0]=0;
q.push(node{1,0,0});
while(!q.empty()){
node k=q.top();
q.pop();
int x=k.x,num=k.num;
if(flag[x][num])continue;
flag[x][num]=1;
for(register int i=head[x];i;i=nxt[i])
{
int kk=to[i];
if(d[kk][num]>max(d[x][num],w[i])){
d[kk][num]=max(d[x][num],w[i]);
if(!flag[kk][num])q.push(node{kk,d[kk][num],num});
}
if(num<T&&d[kk][num+1]>d[x][num]){
d[kk][num+1]=d[x][num];
if(!flag[kk][num+1])q.push(node{kk,d[kk][num+1],num+1});
}
}
}
}
int main()
{
n=read(),m=read(),T=read();
for(register int i=1;i<=m;i++){
int l,r,dis;
l=read(),r=read(),dis=read();
add(l,r,dis);
}
dijkstra();
if(d[n][T]!=inf)
printf("%d\n",d[n][T]);
else printf("-1\n");
return 0;
}
下面再提供一份分层图最短路的代码
#include <bits/stdc++.h>
using namespace std;
const int N=100050;
int to[N],w[N],n,K,m,cnt,nxt[N],head[N],d[N],vis[N],s,t;
int read(){
int res=0,kkk=1;char ch=' ';
while(!isdigit(ch)){ch=getchar();if(ch=='-')kkk=-1;}
while(isdigit(ch)){res=res*10+ch-'0';ch=getchar();}
return res*kkk;
}
void qxx(int x,int y,int dis){
to[++cnt]=y;
w[cnt]=dis;
nxt[cnt]=head[x];
head[x]=cnt;
}
void add(int x,int y,int z){
qxx(x,y,z),qxx(y,x,z);
}
struct node{
int x,d;
friend bool operator<(node x,node y){
return x.d>y.d;
}
};
priority_queue<node>q;
void dijkstra(){
memset(d,63,sizeof(d));
q.push(node{s,0});
d[s]=0;
while(!q.empty()){
int k=q.top().x;
q.pop();
if(vis[k])continue;
vis[k]=1;
for(register int i=head[k];i;i=nxt[i]){
int kk=to[i];
if(d[kk]>max(d[k],w[i]))
{
d[kk]=max(d[k],w[i]);
if(!vis[kk]){
q.push(node{kk,d[kk]});
}
}
}
}
}
int main()
{
n=read(),m=read(),K=read();
s=1,t=n;
for(register int i=1;i<=m;i++){
int l=read(),r=read(),q=read();
add(l,r,q);
for(register int j=1;j<=K;j++){
add(j*n+l,j*n+r,q);
qxx((j-1)*n+l,j*n+r,0);
qxx((j-1)*n+r,j*n+l,0);
}
}
dijkstra();
if(d[K*n+t]!=1061109567)//初始化的值若没有改变就说明无解
printf("%d\n",d[K*n+t]);
else printf("-1\n");
return 0;
}
如果有需要的话,可以看看这里,讲解的还是很赞的ovo
虽然最后有神仙告诉蒟蒻二分+spfa就是分层图,但是我还是要发题解qaq