-
题意:一个n点m边的无向图,其中k条边的权值可以变为0,求s到t的最短路
-
思路:分层图的思想orz
dis[i][j]表示到达第i个点且将j条边的权值变为0的最短路
每次更新最优有两种更新方法,一种使普通的最短路更新,另一种就是将这条边权值变为0更新。 -
代码:
#include<bits/stdc++.h>
using namespace std;
const int INF=INT_MAX/2-10;
int n,m,s,t,k;
struct node{
int v,w,k;
node(){};
bool operator <(const node &x) const{
return x.w<w;
}
};
vector<node> v[1005];
priority_queue<node> q;
int dis[1005][1005];
int is[1005][1005];
void dij(int s){
for(int i=1;i<=n;i++){
for(int j=0;j<=k;j++){
dis[i][j]=INF;
}
}
dis[s][0]=0;
//is[s][0]=1;
node f;
f.v=s;
f.w=0;
f.k=0;
q.push(f);
while(!q.empty()){
f=q.top(); q.pop();
int g=f.v;
int lv=f.k;
if(is[g][lv]==1) continue;
is[g][lv]=1;
for(int i=0;i<v[g].size();i++){
//两种变优
if(v[g][i].w+dis[g][lv]<dis[v[g][i].v][lv]){//不用变0方法
dis[v[g][i].v][lv]=v[g][i].w+dis[g][lv];
node ff;
ff.v=v[g][i].v;
ff.k=lv;
ff.w=dis[v[g][i].v][lv];
q.push(ff);
}
if(lv<k){//用变0方法
if(dis[g][lv]<dis[v[g][i].v][lv+1]){
dis[v[g][i].v][lv+1]=dis[g][lv];
node ff;
ff.v=v[g][i].v;
ff.k=f.k+1;
ff.w=dis[v[g][i].v][lv+1];
q.push(ff);
}
}
}
}
}
int main(){
scanf("%d %d %d %d %d\n",&n,&m,&s,&t,&k);
int i,j;
for(i=0;i<m;i++){
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
node f;
f.v=y;f.w=z;
v[x].push_back(f);
f.v=x;
v[y].push_back(f);
}
// for(i=1;i<=n;i++){
// printf("%d\n",i);
// for(j=0;j<v[i].size();j++){
// printf("%d %d\n",v[i][j].v,v[i][j].w);
// }
// }
dij(s);
int ans=dis[t][0];
for(i=1;i<=k;i++){
ans=min(ans,dis[t][i]);
}
printf("%d\n",ans);
}