POJ3662 Telephone Lines( dijkstral + 二分 )

  POJ3662 Telephone Lines

    题目大意:要在顶点1到顶点n之间建一条路径,假设这条路径有m条边,其中有k条边是免费的,剩余m-k条边是要收费的,

        求这m-k条边中花费最大的一条边的最小花费.

    让m条边中原本花费最大的k条边成为免费的边,则这时m-k条边中花费最大的一条边的花费最小.

    二分枚举m-k条边中花费最大的一条边的最小花费x,dijkstra求最短路径时,将花费大于x的边的花费设为1(花费为INF的边不变),花费小于等于x的边设为

0,则d[v-1]中返回的就是花费大于x的边数,当返回值小余等于k时,说明mid小了,ub=mid,否则,lb=mid+1;

  最后输出mid或lb即可

    一开始我的dijkstra未用队列优化,954ms飘过,用邻接矩阵存储时一开始一定要把所有边都初始化为INF,对cost[v][u]判断时,花费为INF的边不变

    未优化的dijkstra

    

/*
* Created:     2016年04月03日 14时11分34秒 星期日
* Author:      Akrusher
*
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define in(n) scanf("%d",&(n))
#define in2(x1,x2) scanf("%d%d",&(x1),&(x2))
#define in3(x1,x2,x3) scanf("%d%d%d",&(x1),&(x2),&(x3))
#define inll(n) scanf("%I64d",&(n))
#define inll2(x1,x2) scanf("%I64d%I64d",&(x1),&(x2))
#define inlld(n) scanf("%lld",&(n))
#define inlld2(x1,x2) scanf("%lld%lld",&(x1),&(x2))
#define inf(n) scanf("%f",&(n))
#define inf2(x1,x2) scanf("%f%f",&(x1),&(x2))
#define inlf(n) scanf("%lf",&(n))
#define inlf2(x1,x2) scanf("%lf%lf",&(x1),&(x2))
#define inc(str) scanf("%c",&(str))
#define ins(str) scanf("%s",(str))
#define out(x) printf("%d\n",(x))
#define out2(x1,x2) printf("%d %d\n",(x1),(x2))
#define outf(x) printf("%f\n",(x))
#define outlf(x) printf("%lf\n",(x))
#define outlf2(x1,x2) printf("%lf %lf\n",(x1),(x2));
#define outll(x) printf("%I64d\n",(x))
#define outlld(x) printf("%lld\n",(x))
#define outc(str) printf("%c\n",(str))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define mem(X,Y) memset(X,Y,sizeof(X));
typedef vector<int> vec;
typedef long long ll;
typedef pair<int,int> P;
const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const bool AC=true;

int cost[1005][1005];
int d[1005];
bool used[1005];
int V;
const int MAX_L=1000000;
int dijkstra(int s,int x){
    int pay;
    fill(d,d+V,INF);
    fill(used,used+V,false);
    d[s]=0;
    while(true){
        int v=-1;
        for(int u=0;u<V;u++){ //从未使用的顶点中选取一个距离最小的顶点
            if(!used[u]&&(v==-1||d[v]>d[u])) v=u; //注意此处是v=u;(wa了半天)
        }
        if(v==-1) break; //所有的顶点都被使用过了;
            used[v]=true;

            rep(u,0,V){    //更新最短距离
            if(cost[v][u]>x&&cost[v][u]!=INF) pay=1;//注意此处的判断,大于x的还有可能为INF,此处是pay=1,不是cost[v][u]=1;
            else if(cost[v][u]<=x) pay=0;  //等于x的电缆线不需要花钱,也为所求的最大花费的电缆线
            else if(cost[v][u]==INF) pay=INF; //一开始忘了判断这个,wa的不要不要的
            d[u]=min(d[u],d[v]+pay);
        }
    }
return d[V-1];//返回的是比x大的个数
}
int main()
{
    int n,p,k,a,b,c,lb,ub,mid;
    in3(n,p,k);
    V=n;
    fill(cost[0],cost[0]+1005*1005,INF);
    rep(i,0,p){
        in3(a,b,c);
        a--;b--;
        cost[a][b]=c;
        cost[b][a]=c;
    }
    lb=0,ub=MAX_L+1;//边的最大值为1000000
    while(ub>lb){  //二分时mid总是向下取整,区间小的时候让lb=mid+1,相等时让ub=mid则不会陷入死循环
        mid=(ub+lb)>>1;//位移运算符更高效
        if(dijkstra(0,mid)<=k) ub=mid;
        else lb=mid+1;
    }
    if(lb==MAX_L+1) printf("-1\n");
    else out(ub);
    return 0;
}

一下是用优先队列优化,时间是125ms;

  

/*
* Created:     2016年04月03日 14时11分34秒 星期日
* Author:      Akrusher
*
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define in(n) scanf("%d",&(n))
#define in2(x1,x2) scanf("%d%d",&(x1),&(x2))
#define in3(x1,x2,x3) scanf("%d%d%d",&(x1),&(x2),&(x3))
#define inll(n) scanf("%I64d",&(n))
#define inll2(x1,x2) scanf("%I64d%I64d",&(x1),&(x2))
#define inlld(n) scanf("%lld",&(n))
#define inlld2(x1,x2) scanf("%lld%lld",&(x1),&(x2))
#define inf(n) scanf("%f",&(n))
#define inf2(x1,x2) scanf("%f%f",&(x1),&(x2))
#define inlf(n) scanf("%lf",&(n))
#define inlf2(x1,x2) scanf("%lf%lf",&(x1),&(x2))
#define inc(str) scanf("%c",&(str))
#define ins(str) scanf("%s",(str))
#define out(x) printf("%d\n",(x))
#define out2(x1,x2) printf("%d %d\n",(x1),(x2))
#define outf(x) printf("%f\n",(x))
#define outlf(x) printf("%lf\n",(x))
#define outlf2(x1,x2) printf("%lf %lf\n",(x1),(x2));
#define outll(x) printf("%I64d\n",(x))
#define outlld(x) printf("%lld\n",(x))
#define outc(str) printf("%c\n",(str))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define mem(X,Y) memset(X,Y,sizeof(X));
typedef vector<int> vec;
typedef long long ll;
typedef pair<int,int> P;
const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const bool AC=true;

struct edge{int to,cost;};
typedef pair<int,int> P; //first是最短距离,second是顶点编号
int V;
vector<edge> G[1005];
int d[1005];
const int MAX_L=1000000;
int dijkstra(int s,int x){
    priority_queue <P,vector<P>,greater<P> > que;
    fill(d,d+V,INF);
    d[s]=0;
    que.push(P(0,s));
    while(!que.empty()){
        P p=que.top();que.pop();
        int v=p.second;
        if(d[v]<p.first) continue;
        rep(i,0,G[v].size()){
            edge e=G[v][i];
            if(e.cost>x) e.cost=1;
            else e.cost=0;
            if(d[e.to]>d[v]+e.cost){
                d[e.to]=d[v]+e.cost;
                que.push(P(d[e.to],e.to));
                }
            }
        }
return d[V-1];//返回的是比x大的个数
}
int main()
{
    int n,p,k,a,b,c,lb,ub,mid;
    in3(n,p,k);
    V=n;

    rep(i,0,p){
        in3(a,b,c);
        a--;b--;
        edge e;
        e.to=b;
        e.cost=c;
        G[a].push_back(e);
        e.to=a;
        e.cost=c;
        G[b].push_back(e);//没有重边才能这样赋值
    }
    lb=0,ub=MAX_L+1;//边的最大值为1000000
    while(ub>lb){  //二分时mid总是向下取整,区间小的时候让lb=mid+1,相等时让ub=mid则不会陷入死循环
        mid=(ub+lb)>>1;//位移运算符更高效
        if(dijkstra(0,mid)<=k) ub=mid;
        else lb=mid+1;
    }
    if(lb==MAX_L+1) printf("-1\n");
    else out(ub);
    return 0;
}

    

时间: 2024-10-28 23:00:09

POJ3662 Telephone Lines( dijkstral + 二分 )的相关文章

poj3662 Telephone Lines【最短路】【二分】

http://poj.org/problem?id=3662 Telephone Lines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions:9310   Accepted: 3374 Description Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative,

POJ3662 Telephone Lines (dijkstra+二分)

Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of the cables required to connect his farm to the phone system. There are N (1 ≤ N ≤ 1,000) forlorn telephone pol

USACO 2008 JAN Telephone Lines 【二分答案、SPFA】

题目 题目描述 Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of the cables required to connect his farm to the phone system. There are N (1 ≤ N ≤ 1,000) forlorn telep

POJ 3662 Telephone Lines(二分答案+SPFA)

[题目链接] http://poj.org/problem?id=3662 [题目大意] 给出点,给出两点之间连线的长度,有k次免费连线, 要求从起点连到终点,所用的费用为免费连线外的最长的长度. 求最小费用. [题解] 二分答案,对于大于二分答案的边权置为1,小于等于的置为0, 则最短路就是超出二分答案的线数,如果小于等于k,则答案是合法的 [代码] #include <cstdio> #include <cstring> using namespace std; const i

[POJ3662] Telephone Lines

题意:n个点,m条边,有k次机会免费走过一条边,最小化1-n的最大边权 题解:spfa+二分 这题好像克我......,一开始写了个二分+spfa在洛谷上A了,poj上莫名wa掉 然后写另一种方法,读入读成点数了,一直没发现,wa了一万年...... 二分最大边权 check把大于mid的边赋为1,小于等于mid的赋为0,spfa即可 #include<iostream> #include<cstdio> #include<cstdlib> #include<cs

P1948 [USACO08JAN]电话线Telephone Lines spfa 二分答案

多年以后,笨笨长大了,成为了电话线布置师.由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人.该市周围分布着N(1<=N<=1000)根据1……n顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有p(1<=p<=10000)对电话杆可以拉电话线.其他的由于地震使得无法连接. 第i对电线杆的两个端点分别是ai,bi,它们的距离为li(1<=li<=1000000).数据中每对(ai,bi)只出现一次.编号为1的电话杆已经接入了全国的电话网络,整个

POJ 3662 Telephone Lines【Dijkstra最短路+二分求解】

Telephone Lines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7214   Accepted: 2638 Description Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of

poj 3662 Telephone Lines(最短路+二分)

Telephone Lines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6973   Accepted: 2554 Description Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of

[bzoj1614][Usaco2007Jan]Telephone Lines 架设电话线_二分答案_最短路

Telephone Lines bzoj-1614 Usaco-2007Jan 题目大意:给你一个n个点m条边的带边权无向图,求最短路.可以选取k条边免费. 注释:$1\le n\le 10^3$,$1\le m\le 10^5$ 想法:一眼分层图最短路啊! 我都想出来了就上网查一下题解吧 卧槽??二分+spfa?? 其实这个题不用分层图 我们二分答案,二分出最大值,然后将图中所有比mid大的边设为1,小的设为0,然后跑最短路.如果最短路的值比k大,说明最大值一定比二分的mid大.因为我的最短路