zoukankan      html  css  js  c++  java
  • poj3662Telephone Lines——二分+最短路

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

    二分答案找出符合条件的最小长度;

    假设了每个长度后,以这个为标准对每条边赋值,0为小于等于,1为大于,然后按这个值来跑最短路,在看看能否使用不超过k根长电线;

    注意不能到达要输出-1!

    不知为何l从0开始就A了,从最短的电线开始就是WA,可怖的细节;

    总之,0和1这个技巧很美,打破了最短路的常规思路。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    queue<int>q;
    int n,p,k,head[1005],ct,l,r,dis[1005];
    bool vis[1005];
    struct N{
        int to,next,w,c;
        N(int t=0,int n=0,int w=0):to(t),next(n),w(w) {}
    }edge[20005];
    bool spfa()
    {    
        memset(vis,0,sizeof vis);
        memset(dis,3,sizeof dis);
        while(q.size())q.pop();
        q.push(1);vis[1]=1;dis[1]=0;
        while(q.size())
        {
            int x=q.front();q.pop();
            vis[x]=0;
            for(int i=head[x];i;i=edge[i].next)
            {
                int u=edge[i].to;
                if(dis[u]>dis[x]+edge[i].c)
                {
                    dis[u]=dis[x]+edge[i].c;
                    if(!vis[u])
                    {
                        vis[u]=1;
                        q.push(u);
                    }
                }
            }
        }
        return dis[n]<=k;
    }
    bool cl(int x)
    {
        for(int i=1;i<=ct;i++)
        {
            if(edge[i].w<=x)edge[i].c=0;
            else edge[i].c=1;
        }
        return spfa();
    }
    int main()
    {
        while(scanf("%d%d%d",&n,&p,&k)==3)
        {
            ct=0;
            memset(head,0,sizeof head);
    //        l=1000005;//!!
            l=0;
            r=0;
            int x,y,z;
            for(int i=1;i<=p;i++)
            {
                scanf("%d%d%d",&x,&y,&z);
                edge[++ct]=N(y,head[x],z);head[x]=ct;
                edge[++ct]=N(x,head[y],z);head[y]=ct;
                r=max(r,z);
    //            l=min(l,z);
            }
    //        while(l<r)
    //        {
    //            int mid=(l+r)/2;
    //            if(cl(mid))r=mid;
    //            else l=mid+1;
    //        }
            int ans=-1;//!!!
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(cl(mid))
                {
                    ans=mid;
                    r=mid-1;
                }
                else l=mid+1;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    WinForm笔记1:TextBox编辑时和DataGridView 单元格编辑时 的事件及其顺序
    Emgu 学习(4) 使用指针访问图像内存
    SolidWorks学习笔记1
    Emgu 学习(3) 绘图,使用鼠标绘图,使用trackbar
    NModbus4的使用
    C# async await的使用
    Emgu 学习(2) 视频文件播放
    redis-key2
    redis--key1
    rpc优化
  • 原文地址:https://www.cnblogs.com/Zinn/p/8698385.html
Copyright © 2011-2022 走看看