poj之旅——3662

题目描述:N个电线杆P条线可选,K条线内免费,否则花费免费额度外最长的那一根。


最小花费


题解:二分答案,模式同最大值最小化。


Check(mid):


建图。


因为mid可能就是结果,故将原图按照边权是否大于mid重新建图,用dijsktra求1到n



最短路,d[n]即表示所需免费数,与k比较大小,调整l与r。


参考程序:

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<vector>
#define maxn 2100
using namespace std;
int K;
struct Edge{
	int dist,to;
	Edge(int dist,int to):dist(dist),to(to){}
	bool operator < (const Edge& rhs)const{
		return dist>rhs.dist;
	}
};
struct Dijsktra{
	vector<Edge> G[maxn],G2[maxn];
	bool done[maxn];
	int d[maxn];
	int n;
	void init(int n){
		this->n=n;
		for (int i=0;i<n;i++)G[i].clear();
	}
	void addedge(int a,int b,int c){
		G[a].push_back(Edge(c,b));
		G[b].push_back(Edge(c,a));
	}
	bool Check(int k){
		priority_queue<Edge> Q;
		memset(done,0,sizeof(done));
		memset(d,0x3f,sizeof(d));
		Q.push(Edge(0,0));d[0]=0;	
		while (!Q.empty()){
			Edge now=Q.top();Q.pop();
			int u=now.to;
			if (done[u])continue;
			done[u]=true;
			for (int i=0;i<G[u].size();i++){
				Edge e=G[u][i];
				if (d[u]+(e.dist>k?1:0)<d[e.to]){
					d[e.to]=d[u]+(e.dist>k?1:0);
					if (!done[e.to])Q.push(Edge(d[e.to],e.to));
				}
			}
		}
		return d[n-1]<=K;
	}
}map;
int main(){
	int N,P;
	scanf("%d%d%d",&N,&P,&K);
	map.init(N);
	int r=0;
	for (int i=0;i<P;i++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		a--;b--;
		r=max(r,c);
		map.addedge(a,b,c);
	}
	int l=0;r+=2;int limit=r;
	while (l<r){
		int mid=(l+r)>>1;
		if (map.Check(mid))r=mid;
			else l=mid+1;
	}
	printf("%d",(l>limit-2?-1:l));
	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值