时间限制 : - MS 空间限制 : 65536 KB
评测说明 : 时限1000ms
问题描述
每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M.
道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N; 1 <= P2_i<= N). John需要T_i (1 <=
T_i <= 1,000,000)时间单位用道路i从P1_i走到P2_i或者从P2_i 走到P1_i
他想更新一些路经来减少每天花在路上的时间.具体地说,他想更新K (1 <= K <=
20)条路经,将它们所须时间减为0.帮助FJ选择哪些路经需要更新使得从1到N的时间尽量少.
输入格式
- 第一行: 三个空格分开的数: N, M, 和 K
- 第2..M+1行: 第i+1行有三个空格分开的数:P1_i, P2_i, 和 T_i
输出格式
第一行: 更新最多K条路经后的最短路经长度
.
样例输入
4 4 1
1 2 10
2 4 10
1 3 1
3 4 100
样例输出
1
提示
样例说明:
K是1; 更新道路3->4使得从3到4的时间由100减少到0. 最新最短路经是1->3->4,总用时为1单位. N<=10000
题解
多维最短路 考虑dis[n][k]表示到n点免费k条边的最小值。
所以:1.dis[en][k]=min(dis[en][k],dis[x][k]+len[i]);
2.dis[en][k+1]=min(dis[x][k],dis[en][k+1]);
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
using namespace std;
#define maxn2 110000
int n,m,k;
struct node{
int a,b,d;
};
priority_queue<node>q;
bool operator <(node a,node b)
{
return a.d>b.d;
}
int cnt;
int Last[maxn2],Next[maxn2],End[maxn2],Len[maxn2];
int dis[maxn2][21];
bool mark[maxn2][21];
void insert(int x,int y,int z)
{
Next[++cnt]=Last[x];
Last[x]=cnt;
End[cnt]=y;
Len[cnt]=z;
}
void d(int x)
{
int i,m;
node tmp;
memset(dis,60,sizeof(dis));
dis[x][0]=0;
tmp.a=x;tmp.b=0;tmp.d=dis[x][0];
q.push(tmp);
while(q.size())
{
int s,kk;
node temp=q.top();
q.pop();
s=temp.a;
kk=temp.b;
if(mark[s][kk]==true) continue;
mark[s][kk]=true;
for(i=Last[s];i;i=Next[i])
{
int en=End[i];
if(dis[en][kk]>dis[s][kk]+Len[i])
{
dis[en][kk]=dis[s][kk]+Len[i];
tmp.a=en;tmp.b=kk;tmp.d=dis[en][kk];
q.push(tmp);
}
if(kk+1<=k&&dis[s][kk]<dis[en][kk+1])
{
dis[en][kk+1]=dis[s][kk];
tmp.a=en;tmp.b=kk+1;tmp.d=dis[en][kk+1];
q.push(tmp);
}
}
}
}
int main()
{
int i;
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
insert(y,x,z);
}
d(1);
cout<<dis[n][k];
}