版权声明:转载请附上地址 https://blog.csdn.net/weixin_44574520/article/details/87556935
行动!行动!
Description
大CX国的大兵Jack接到一项任务:敌方占领了n座城市(编号0~n-1),有些城市之间有双向道路相连。Jack需要空降在一个城市S,并徒步沿那些道路移动到T城市。虽然Jack每从一个城市到另一个城市都会受伤流血,但大CX国毕竟有着“过硬”的军事实力,它不仅已经算出Jack在每条道路上会损失的血量,还给Jack提供了k个“简易急救包”,一个包可以让Jack在一条路上的流血量为0。Jack想知道自己最少会流多少血,不过他毕竟是无脑的大兵,需要你的帮助。
Input
第一行有三个整数n,m,k,分别表示城市数,道路数和急救包个数。
第二行有两个整数,S,T。分别表示Jack空降到的城市编号和最终要到的城市。
接下来有m行,每行三个整数a,b,c,表示城市a与城市b之间有一条双向道路。
Output
Jack最少要流的血量。
Sample Input
5 6 1
0 3
3 4 5
0 1 5
0 2 100
1 2 5
2 4 5
2 4 3
Sample Output
8
HINT
【说明】
对于100%的数据,2<=n<=10000,1<=m<=50000,0<=k<=10.
9组为8*1000的网格针对数据,不加优化的spfa只能得10分。
附:优先队列语法参考:
struct node{
int dis,pos;
node():dis(0),pos(0){}//无参初始化
node(int a,int b):dis(a),pos(b){}//带参初始化
bool operator <(node x)const //重载小于运算,用于把priority_queue变成小根堆
{
return dis>x.dis;
}
};
然后在主模块中这样操作:
priority_queue<node> q;
q.push(node(x,0));
node cur=q.top();
q.pop();
q.push(cur);
题目分析:
定义d[i][j],表示起点到i号点用了j个包的最短距离;每次spfa判断时分用包和不用包讨论
Code:
#include <bits/stdc++.h>
using namespace std;
#define maxn 100100
#define maxm 500100
int n,m,k,s,t,size=0,head[maxm],vis[maxn][15],d[maxn][15];
struct node{
int v,w,next;
}e[maxm];
struct cmp{
int v,bk;
bool operator < (const cmp &aa) const
{
return d[v][0] > d[aa.v][0];
}
};
inline int read_(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
inline void clean_(){
memset(d,0x3f,sizeof(d));
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
}
inline void add_(int u,int v,int w){
e[size].v=v;
e[size].w=w;
e[size].next=head[u];
head[u]=size++;
}
inline void spfa_(){
priority_queue<cmp> q;
for(int i=0;i<=k;i++) d[s][i]=0;
q.push((cmp){s,0});
vis[s][0]=1;
while(!q.empty()){
cmp pp=q.top();
int x=pp.v;
int bk=pp.bk;
q.pop();
vis[x][bk]=0;
for(int i=head[x];~i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(d[v][bk]>d[x][bk]+w){//不用包
d[v][bk]=d[x][bk]+w;
if(!vis[v][bk]){
q.push((cmp){v,bk} );
vis[v][bk]=1;
}
}
if(bk<k&&d[v][bk+1]>d[x][bk]){//用包
d[v][bk+1]=d[x][bk];
if(!vis[v][bk+1]){
q.push((cmp){v,bk+1});
vis[v][bk+1]=1;
}
}
}
}
}
inline void init_(){
freopen("xdong.txt","r",stdin);
}
inline void readda_(){
clean_();
n=read_();m=read_();k=read_();
s=read_();t=read_();
int a,b,z;
for(int i=0;i<m;i++){
a=read_();b=read_();z=read_();
add_(a,b,z);add_(b,a,z);
}
}
inline void work_(){
int ans=99999999;
spfa_();
for(int i=0;i<=k;i++) ans=min(ans,d[t][i]);
printf("%d",ans);
}
int main(){
init_();
readda_();
work_();
return 0;
}