zoukankan      html  css  js  c++  java
  • P1948 [USACO08JAN]电话线Telephone Lines

    传送门

    思路:

      二分+最短路径:可以将长度小于等于 mid 的边视为长度为 0 的边,大于 mid 的边视为长度为 1 的边,最后用 dijkstra 检查 d [ n ] 是否小于等于 k 即可。

    标程:

    #include<cstring>
    #include<queue>
    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<fstream>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    #include<stack>
    #include<map>
    #include<set>
    #include<deque>
    #include<string>
    using namespace std;
    #define maxn 100100
    #define INF 0x3f3f3f3f
    priority_queue<pair< int,int >,vector<pair<int,int> >,greater<pair<int,int > > > q;
    struct hh
    {
        int u,v,w,nex;
    }t[maxn<<1];
    int d[maxn<<1],head[maxn<<1],jla[maxn<<1];//jla记录每条边的边长 
    int n,m,p,s=1,cnt=0,ans=INF;//ans记录答案 
    bool vis[maxn<<1];
    inline int read()
    {
        int kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(ls=='-') 
                kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return kr*xs;
    }
    inline void add(int x,int y,int z)
    {
        t[++cnt].u=x;
        t[cnt].v=y;
        t[cnt].w=z;
        t[cnt].nex=head[x];
        head[x]=cnt;
    }//链式前向星加边 
    inline bool dijkstra(int now)
    {
        for(int i=1;i<=n;i++)
        {
            d[i]=INF;
            vis[i]=false;
        }
        d[s]=0;
        q.push(make_pair(d[s],s));
        while(!q.empty())
        {
            int k=q.top().second;
            q.pop();
            if(vis[k]) continue;
            else
            {
                vis[k]=true;
                for(int i=head[k];i!=-1;i=t[i].nex)
                {
                    if(t[i].w>now)
                        if(d[t[i].v]>d[k]+1)
                        {
                            d[t[i].v]=d[k]+1;
                            q.push(make_pair(d[t[i].v],t[i].v));
                        }//如果t[i].v的边大于当前二分的答案,那么就要使用一次名额
                    if(t[i].w<=now)
                        if(d[t[i].v]>d[k])
                        {
                            d[t[i].v]=d[k];
                            q.push(make_pair(d[t[i].v],t[i].v));
                        }//如果t[i].v的边不大于当前二分的答案,那么就无需使用名额,直接松弛操作
                }
            }
        }
        if(d[n]>p) return false;//如果到达n的次数大于免费的次数限制,那么当前答案不可行
        return true;//反之,则可行 
    }
    int main()
    {
        n=read();m=read();p=read();
        for(int i=1;i<=n;i++)
          head[i]=-1;
        int xx,yy,zz;
        for(int i=1;i<=m;i++)
        {
            xx=read();yy=read();zz=read();
            add(xx,yy,zz);
            add(yy,xx,zz);
            jla[i]=zz;
        }
        sort(jla+1,jla+m+1);//将所有的边从小到大排序,为二分做准备
        if(dijkstra(0))
        {
            printf("0
    ");
            return 0;
        }
        if(!dijkstra(jla[m]))
        {
            printf("-1
    ");
            return 0;
        }//两个特判,,, 
        int l=1,r=m;
        while(l<=r)
        {
            int mid=l+r>>1;//二分查找 
            if(dijkstra(jla[mid]))
            {
                ans=min(ans,jla[mid]);
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%d
    ",ans);//输出答案 
    return 0;
    }

      

  • 相关阅读:
    2019-2020-1 20175323 实验四 外设驱动程序设计
    2019-2020-1 20175323 实验三 并发程序
    2019-2020-1-20175332 20175323 20175228-实验二固件程序设计
    2019-2020-1 20175323 20175332 20175228 实验一开发环境的熟悉
    20175323 团队项目 服务器端函数功能与业务逻辑详解
    2018-2019-2-20175323 java实验五 网络编程与安全
    2018-2019-2-20175323 java实验四 Android程序设计
    2018-2019-2-20175323 java实验三敏捷开发与XP实践
    2018-2019-2-20175323 java实验二《Java面向对象程序设计》
    2018-2019-2 20175323 实验一《Java开发环境的熟悉》实验报告
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9691193.html
Copyright © 2011-2022 走看看