USACO08JAN Telephone Lines 题解

题面

比较显然的,题干问的是第k+1长的路最短;

那么二分答案是正确的方向;

但是怎么验证?

我们可以将所有边权大于二分的答案的边视为边权是1,否则看成0;

然后从1~n跑最短路,如果答案大于二分的答案那么就不成立,否则成立;

这种思维比较重要,代码还是很简单的;

#include <bits/stdc++.h>
using namespace std;
int head[2000010],cnt;
class littlestar{
	public:
		int to;
		int nxt;
		int w;
		void add(int u,int v,int gg){
			nxt=head[u];
			to=v;
			w=gg;
			head[u]=cnt;
		}
}star[2000010];
int n,p,k;
int dis[100010],vis[100010];
bool SPFA(int x)
{
	queue<int> q;
	memset(dis,0x3f,sizeof(dis));
	dis[1]=0;
	memset(vis,0,sizeof(vis));
	q.push(1);
	while(q.size()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i;i=star[i].nxt){
			int v=star[i].to;
			if(dis[v]>dis[u]+(star[i].w>x)){
				dis[v]=dis[u]+(star[i].w>x);
				if(!vis[v]){
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
	if(dis[n]<=k) return 1;
	else{
		return 0;
	} 
}
int main()
{
	cin>>n>>p>>k;
	for(int i=1;i<=p;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		star[++cnt].add(u,v,w);
		star[++cnt].add(v,u,w);
	}
	int l=0,r=1000000;
	while(l<r){
		int mid=(l+r)/2;
		if(SPFA(mid)){
			r=mid;
		}
		else{
			l=mid+1;
		}
	}
	if(l==1000000) l=-1;
	cout<<l<<endl;
}

猜你喜欢

转载自www.cnblogs.com/kamimxr/p/11650105.html
今日推荐