• 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
    ",(x))
    #define out2(x1,x2) printf("%d %d
    ",(x1),(x2))
    #define outf(x) printf("%f
    ",(x))
    #define outlf(x) printf("%lf
    ",(x))
    #define outlf2(x1,x2) printf("%lf %lf
    ",(x1),(x2));
    #define outll(x) printf("%I64d
    ",(x))
    #define outlld(x) printf("%lld
    ",(x))
    #define outc(str) printf("%c
    ",(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
    ");
        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
    ",(x))
    #define out2(x1,x2) printf("%d %d
    ",(x1),(x2))
    #define outf(x) printf("%f
    ",(x))
    #define outlf(x) printf("%lf
    ",(x))
    #define outlf2(x1,x2) printf("%lf %lf
    ",(x1),(x2));
    #define outll(x) printf("%I64d
    ",(x))
    #define outlld(x) printf("%lld
    ",(x))
    #define outc(str) printf("%c
    ",(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
    ");
        else out(ub);
        return 0;
    }

        

  • 相关阅读:
    PhpStorm中如何调整字体大小
    PhpStorm-2017.1.2破解步骤
    Eclipse/MyEclipse 最最常用的快捷键
    Invalid result location value/parameter
    系统重装--相关问题
    喜马拉雅||亲爱的,慢慢行走
    QQ聊天界面模式切换
    myeclipse中如何修改项目的名称
    软考-程序设计语言基础(编译原理)
    软考-计算机组成原理、体系机构与网络安全
  • 原文地址:https://www.cnblogs.com/akrusher/p/5350043.html
走看看 - 开发者的网上家园