题目链接:https://ac.nowcoder.com/acm/contest/884/J
题意:给定一个无向图,有n个点,m条边(n,m<=1e3),起点S、终点T,在可以将k条边的权值变为0的条件下求S到T的最短路。
思路:这种题目要将原图分为k+1层,第i层表示将i条边的权值变为0,在这个图上dijkstra,答案为min(dis[T+i*m])(0<=i<=k)。
AC代码:
#include<cstdio> #include<algorithm> #include<queue> using namespace std; struct node{ int v,w,nex; }edge[2005*2005]; int n,m,S,T,k,cnt,ans=0x3f3f3f3f; int head[1005*1005],dis[1005*1005]; void adde(int u,int v,int w){ edge[++cnt].v=v; edge[cnt].w=w; edge[cnt].nex=head[u]; head[u]=cnt; } struct node2{ int idx,val; node2(){} node2(int i,int v){ idx=i,val=v; } }; bool operator<(node2 a,node2 b){ return a.val>b.val; } void dijkstra(){ for(int i=1;i<=n*(k+1);++i) dis[i]=0x3f3f3f3f; dis[S]=0; priority_queue<node2> que; que.push(node2(S,0)); while(!que.empty()){ node2 now=que.top(); que.pop(); int x=now.idx,y=now.val; for(int i=head[x];i;i=edge[i].nex){ int v=edge[i].v; if(dis[v]>y+edge[i].w){ dis[v]=y+edge[i].w; que.push(node2(v,dis[v])); } } } } int main(){ scanf("%d%d%d%d%d",&n,&m,&S,&T,&k); for(int i=1;i<=m;++i){ int u,v,w; scanf("%d%d%d",&u,&v,&w); for(int j=0;j<k;++j){ adde(u+j*m,v+j*m,w); adde(v+j*m,u+j*m,w); adde(u+j*m,v+(j+1)*m,0); adde(v+j*m,u+(j+1)*m,0); } adde(u+k*m,v+k*m,w); adde(v+k*m,u+k*m,w); } dijkstra(); for(int i=0;i<=k;++i) if(dis[T+i*m]<ans) ans=dis[T+i*m]; printf("%d ",ans); return 0; }