题目描述 Description
由于地震使得连接汶川县城电话线全部损坏,假如你是负责将电话线接到震中汶川县城的负责人,汶川县城周围分布着N(1≤N≤1,000)根按 1..N 顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连。一共P(1≤P≤10,000)对电话线杆间可以拉电话线,其余的由于地震使得无法被连接。
第i对电话线杆的两个端点分别为Ai,Bi,它们间的距离为Li(1≤Li≤1,000,000)。数据中保证每对(Ai,Bi)最多只出现1次。编号为1的电话线杆已经接人了全国的电话网络,整个县城的电话线全都连到了编号为N的电话线杆上。也就是说,你的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连人电话网络。
电信公司决定支援灾区免费为汶川县城连结K(0≤K
输入描述 Input Description
输入文件的第一行包含三个用空格隔开的整数:N,P和K。
第二行到第P+1行:每行分别都为空格隔开的整数:Ai,Bi和Li。
输出描述 Output Description
输出文件中仅包含一个整数,表示在这项工程上的最小支出。如果任务不可能完成,则输出-1。
样例输入 Sample Input
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
样例输出 Sample Output
4
思路
根据题目描述,我们可以很容易的得出这道题需用最短路算法。
关于k的取值,我们可以二分。
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1000000+5;
int n,m,k,num,head[N],dis[N],flag[N];
queue<int>q;
struct edge
{
int u,v,w;
int next;
}ed[N];
void build(int u,int v,int w)
{
ed[++num].u=u;
ed[num].v=v;
ed[num].w=w;
ed[num].next=head[u];
head[u]=num;
}
void SPFA(int s)
{
memset(flag,0,sizeof(flag));
memset(dis,inf,sizeof(dis));
dis[1]=0;flag[1]=0;
q.push(1);
while(!q.empty())
{
int u=q.front();
q.pop();flag[u]=0;
for (int i=head[u];i;i=ed[i].next)
{
int now,v=ed[i].v;
if (ed[i].w<=s) now=0;
else now=1;
if (dis[v]>dis[u]+now)
{
dis[v]=dis[u]+now;
if (flag[v]==0)
{
q.push(v);
flag[v]=1;
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
build(x,y,z);
build(y,x,z);
}
int l=0,r=N,ans=-1;
while(l<=r)
{
int mid=(l+r)/2;
SPFA(mid);
if (dis[n]<=k) {ans=mid;r=mid-1;}
else l=mid+1;
}
printf("%d",ans);
return 0;
}