Description
Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?
HINT
对于30%的数据,2<=n<=50,1<=m<=300,k=0;
对于50%的数据,2<=n<=600,1<=m<=6000,0<=k<=1;
对于100%的数据,2<=n<=10000,1<=m<=50000,0<=k<=10.
大体意思是求无向图上 s 到 t 的最短路,其中有K条边可以不计它的权值。K最大只有10,可以用 dist[i][j] 表示使用了 j 次免费的机会到达 i 点 的最短路,松弛操作多一种这条路使用免费的机会的情况就好qwq。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int size = 800100;
int n,m,k;
int head[size],next[size],dist[size][11];
bool use[size][11];
struct dc
{
int t,d;
}l[size];
int tot = 1;
void build(int f,int t,int d)
{
l[tot].t = t;
l[tot].d = d;
next[tot] = head[f];
head[f] = tot ++;
}
queue < int > q;
void spfa(int s)
{
for(int i = 0 ; i <= n ; i ++)
for(int j = 0 ; j <= k ; j ++)
dist[i][j] = 214748364;
dist[s][0] = 0;
use[s][0] = 1;
q.push(s);
q.push(0);
while(!q.empty())
{
int f = q.front();
q.pop();
int time = q.front();
q.pop();
use[f][time] = 0;
for(int i = head[f] ; i ; i = next[i])
{
int t = l[i].t;
if(dist[t][time] > dist[f][time] + l[i].d)
{
dist[t][time] = dist[f][time] + l[i].d;
if(!use[t][time])
{
use[t][time] = 1;
q.push(t);
q.push(time);
}
}
if(time < k)
{
if(dist[t][time+1] > dist[f][time])
{
dist[t][time+1] = dist[f][time];
if(!use[t][time+1])
{
use[t][time+1] = 1;
q.push(t);
q.push(time+1);
}
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
int start,end;
scanf("%d%d",&start,&end);
for(int i = 1 ; i <= m ; i ++)
{
int f,t,d;
scanf("%d%d%d",&f,&t,&d);
build(f,t,d);
build(t,f,d);
}
spfa(start);
cout<<dist[end][k];
return 0;
}
传送门 : bzoj 2763