【POJ】3662

来源:互联网 发布:mac的哪款粉底液好用 编辑:程序博客网 时间:2024/05/16 06:01

http://poj.org/problem?id=3662

一共有N个电线杆,有P对电线杆是可以连接的,现要使得杆1和杆N相连,K条电线可以免费使用的,当使用电线的数量超过K条,超出的电线要收费,收的总费用为去掉免费使用的K条电线之后最长的那条电线的长度。现在需要尽可能的减少费用,问最少费用是多少。

解题思路:可以二分搜索出所需费用,这样,对于每一个最小费用‘候选人’,都要进行判定是否符合题目条件,换句话说,如果以此为最少所需费用,那么至少需要多少条免费使用的电线,这个值与K进行比较,如果比K大,
说明以此为最少所需费用的话还偏小,搜索范围的下界改为当前的费用‘候选人’,反之改上界。在判断至少需要多少条免费使用的电线时,可以使用dijkstra算法,此时点与点之间的距离大于等于‘候选人’时,需要免费使用
的电线数量要加1,否则不用加。

#include <iostream>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int INF=0x3f3f3f3f;const int maxV=1001;const int maxE=20001;int N,P,K;int num=0;int dis[maxV];bool vis[maxV];int head[maxV];struct Edge{    int to;    int val;    int next;}e[maxE];void add(int from,int to,int val){    e[num].to=to;    e[num].val=val;    e[num].next=head[from];    head[from]=num++;}int SPFA(int x){    queue<int> q;    memset(vis,false,sizeof(vis));    memset(dis,0x3f,sizeof(dis));    dis[1]=0;    vis[1]=true;    q.push(1);    while (!q.empty()){        int now=q.front();        vis[now]=false;        q.pop();        for (int i=head[now];i!=-1;i=e[i].next){            int t=dis[now]+(e[i].val>=x?1:0);            int v=e[i].to;            if (dis[v]>t){                dis[v]=t;                if (!vis[v]){                    vis[v]=true;                    q.push(v);                }            }        }    }    return dis[N];}int main(){    cin >> N >> P >> K;    memset(head,-1,sizeof(head));    for (int i=0;i<P;i++){        int from,to,val;        cin >> from >> to >> val;        add(from,to,val);        add(to,from,val);    }    int L=0,R=1e6+2;    while (L+1<R){        int mid=(L+R)>>1;        if (SPFA(mid)>K) L=mid;        else R=mid;    }    if (L<=1e6) cout << L << endl;    else cout << "-1" << endl;}
原创粉丝点击