问题 D: 传送门
时间限制: 10 Sec 内存限制: 128 MB题目描述
FJ 每天都要从家里去牧场,再从牧场回家……
FJ从家到牧场的地区可以看作一个N个点和M条双向边的图,家在1号点,牧场在N号点。现在FJ掌握了现代科技,他现在要将一些道路的两端修建双向传送的传送门,这样可以把通过的时间变为0。现在FJ最多可以建K个传送门,FJ想知道他从家到牧场最少需要多少时间?输入
第一行,三个数N,M,K
接下来M 行,每行三个数,表示一条边的两端和长度
输出
一个数,表示最少要用多长时间
样例输入
4 4 11 2 102 4 101 3 13 4 100
样例输出
1
提示
对于100%的数据,N<=10000,M<=50000,K<=20,答案在int 范围内
对于测试点1~6,时限1s
对于测试点7~9,时限3s
对于测试点10,时限10s
可优化
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iomanip>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
struct edge
{
int x,y,w,next;
};
struct status
{
int x,k,dis;
friend bool operator<(status a,status b)
{
return a.dis>b.dis;
}
};
priority_queue<status>q;
edge e[100101];
bool v[50101][101];
int dis[50101][101],ls[100101];
int maxE=0;
void add(int x,int y,int w)
{
e[++maxE]=(edge){x,y,w,ls[x]};
ls[x]=maxE;
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m,k,st,ed;
scanf("%d%d%d",&n,&m,&k);
//scanf("%d%d",&st,&ed);
// cout<<" @@"<<n<<" "<<m<<" "<<k;
st++;ed=n;
for (int i=1;i<=m;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
// x++;y++;
// cout<<x<<" "<<y<<" @@@"<<w<<endl;
add(x,y,w);
add(y,x,w);
}
st=1;ed=n;
for (int i=0;i<=n;i++)
for (int j=0;j<=n;j++)
dis[i][j]=1<<31-1;
dis[st][0]=0;
status o;
o.x=st;
o.k=0;
o.dis=0;
//{st,0,0}
q.push(o);
//cout<<q.empty()<<" ((("<<endl;
v[st][0]=true;
while (!q.empty())
{
status s=q.top();
int now=s.x;
int tmp=s.k;
int jh=s.dis;
//cout<<" "<<now<<" !!!"<<tmp<<" @@@"<<jh;
q.pop();
for (int i=ls[now];i;i=e[i].next)
{
if (e[i].w+dis[now][tmp]<dis[e[i].y][tmp])
{
dis[e[i].y][tmp]=e[i].w+dis[now][tmp];
//cout<<" "<<"***"<<dis[e[i].y][tmp]<<endl;
if (!v[e[i].y][tmp])
{
v[e[i].y][tmp]=true;
q.push((status){e[i].y,tmp,dis[e[i].y][tmp]});
}
}
if (dis[now][tmp]<dis[e[i].y][tmp+1]&&tmp<k)
{
dis[e[i].y][tmp+1]=dis[now][tmp];
if (!v[e[i].y][tmp+1])
{
v[e[i].y][tmp+1]=true;
q.push((status){e[i].y,tmp+1,dis[e[i].y][tmp+1]});
}
}
}
v[now][tmp]=false;
}
//cout<<ed<<" @@@"<<endl;
int ans=1<<31-1;
for (int i=0;i<=n;i++)
{
if(dis[ed][i]<ans)
{
ans=dis[ed][i];
//cout<<
}
}
printf("%d\n",ans);
// while(1);
return 0;
}