<题目链接>
题目大意:
有N个城市,这些城市之间有M条有向边,每条边有权值,能够选择K条边 边权置为0,求1到N的最短距离。
解题分析:
分层图最短路模板题,将该图看成 K+1 层图,然后具体解析见代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define INF 0x7ffffffffff; ; ; typedef long long ll; int n,m,k,tot,cnt; int head[M]; ]; struct EDGE{ int to; int next; ll val; }edge[M<<]; struct NODE{ int loc,cal; //loc代表该点的标号,cal代表该点所在的层数,这两个变量可以确定分层图中所有点的位置 ll dist; bool operator <(const NODE &tmp)const{ return dist>tmp.dist; } NODE(,,ll w=){ loc=a,cal=b,dist=w; } }d[N][]; void init(){ cnt=; memset(head,-,sizeof(head)); } void add(int u,int v,int w){ edge[++cnt].to=v,edge[cnt].val=w; edge[cnt].next=head[u],head[u]=cnt; } void dij(){ memset(vis,false,sizeof(vis)); ;i<=n;i++){ ;j<=k;j++){ d[i][j].dist=INF; //将所有点到起点的距离初始化为无穷大 } } d[][].dist=; priority_queue<NODE>q; q.push(NODE(,,d[][].dist)); while(!q.empty()){ NODE now=q.top(); q.pop(); int tmp1=now.loc,tmp2=now.cal; if(vis[tmp1][tmp2])continue; vis[tmp1][tmp2]=true; for(int i=head[tmp1];~i;i=edge[i].next){ int v=edge[i].to; ll cost=edge[i].val; if(d[v][tmp2].dist>d[tmp1][tmp2].dist+cost){ //在同一层中进行普通的松弛操作,表示当前道路的权值不用置为0 d[v][tmp2].dist=d[tmp1][tmp2].dist+cost; q.push(NODE(v,tmp2,d[v][tmp2].dist)); } <=k&&d[v][tmp2+].dist>d[tmp1][tmp2].dist){ //没有加上cost,代表 tmp1-->v 这段路的权值置为0 d[v][tmp2+].dist=d[tmp1][tmp2].dist; q.push(NODE(v,tmp2+,d[v][tmp2+].dist)); } } } } int main(){ int T;scanf("%d",&T); while(T--){ init(); scanf("%d%d%d",&n,&m,&k); ;i<=m;i++){ int u,v;ll w; scanf("%d%d%lld",&u,&v,&w); add(u,v,w); } dij(); ll mn=INF; ;i<=k;i++){ //在所有层中选取最短的情况 mn=min(mn,d[n][i].dist); } printf("%lld\n",mn); } ; }
2018-09-12