POJ3662-Telephone Lines

  

题目链接

解题思路

     可以免费k条路,然后只需要支付权值最大的一条路。二分。对答案进行二分,小于等于mid的时,将路的权值标为0,大于mid时,将路的权值标为1。(mid是需要支付的,免费k条是大于mid的。因为二分枚举的mid就是答案, 然后如果等于mid的话 mid是答案 也成立)然后求最短路。二分的条件是dis[n]小于等于mid,r=mid;dis[n]大于mid,l=mid+1;

#include<stdio.h>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+177;
const int inf=0x3f3f3f3;
struct Node{
	int next;
	int to;
	int vul;
}edge[maxn];

int vul[maxn]; 

struct node{
	int x;int y;
};
int head[maxn];
int num_edge=0;
int n,p,k;
int dis[maxn];
bool vis[maxn];

typedef pair<int,int >pa;

void add_edge(int from,int to,int vul){
	
	edge[++num_edge].next=head[from];
	edge[num_edge].to=to;
	edge[num_edge].vul=vul;
	head[from]=num_edge;
}

void init(){
	for(int i=0;i<=n+177;i++){
		dis[i]=inf;
		vis[i]=false;
	}
}
void dijkstra(int sta){
	init();
	dis[1]=0;
	priority_queue<pa> pq;
	pa now,tmp;
	now.first=0;
	now.second=sta;
	pq.push(now);
	while(!pq.empty()){
		now=pq.top();
		pq.pop();
		if(dis[now.second]<now.first){
			continue;
		}
		for(int i=head[now.second];i!=0;i=edge[i].next){
			int y=edge[i].to;
			int z=vul[i];
			if(dis[y]>dis[now.second]+z){
				dis[y]=dis[now.second]+z;
				tmp.first=-dis[y];
				tmp.second=y;
				pq.push(tmp);
			}
		}
	}
}



bool jug(int now){
	
	if(now>k){      
		return true;
	}
	return false;
	
}

void change(int now){
	for(int i=0;i<=num_edge;i++){
		if(edge[i].vul<=now){    
			vul[i]=0;
		}else{
			vul[i]=1;
		}
	}
	dijkstra(1);
}

int main(){
	cin>>n>>p>>k;
	int x,y,z;


	for(int i=0;i<p;i++){
		cin>>x>>y>>z;
		add_edge(x,y,z);
		add_edge(y,x,z);
	}	
	
	int l=0,r=inf; 
	while(l<r){
		int mid=(l+r)/2;
		change(mid);

		if(jug(dis[n])){
			l=mid+1;
		}else{
			r=mid;
		}
	}
	if(l>=inf){
		printf("-1\n");
	}else{
		printf("%d\n",l);
	}
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值