• 笨笨的电话网络


    笨笨的电话网络

    题目描述

    多年以后,笨笨长大了,成为了电话线布置师。由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人。该市周围分布着N(1<=N<=1000)根据1……n顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有p(1<=p<=10000)对电话杆可以拉电话线。其他的由于地震使得无法连接。

    第i对电线杆的两个端点分别是ai,bi,它们的距离为li(1<=li<=1000000)。数据中每对(ai,bi)只出现一次。编号为1的电话杆已经接入了全国的电话网络,整个市的电话线全都连到了编号N的电话线杆上。也就是说,笨笨的任务仅仅是找一条将1号和N号电线杆连起来的路径,其余的电话杆并不一定要连入电话网络。

    电信公司决定支援灾区免费为此市连接k对由笨笨指定的电话线杆,对于此外的那些电话线,需要为它们付费,总费用决定于其中最长的电话线的长度(每根电话线仅连接一对电话线杆)。如果需要连接的电话线杆不超过k对,那么支出为0.

    请你计算一下,将电话线引导震中市最少需要在电话线上花多少钱?

    输入格式:

    输入文件的第一行包含三个数字n,p,k;

    第二行到第p+1行,每行分别都为三个整数ai,bi,li。

    输出格式:

    一个整数,表示该项工程的最小支出,如果不可能完成则输出-1.

    输入样例:
    5 7 1
    1 2 5
    3 1 4
    2 4 8
    3 2 3
    5 2 9
    3 4 7
    4 5 6

    输出样例:
    4

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n,p,k,ans,map[1002][1002]={0},a[1002],mapm[1002][1002];
    int l=1000000,r,mid;
    int dist[1002];
    struct node{
        int a,b,l;
    }sz[10002];
    bool f[1002];
    queue<int> q;
    void bfs(){                 //宽搜 
        q.push(1);
        while(q.size()){
            for(int i=1;i<=n;i++)
                if(!f[i]&&map[q.front()][i]){
                    q.push(i);
                    f[i]=1;
                    a[i]=a[q.front()]+1;
                }
                q.pop();
        }
    }
    void dj(){                 //最短路 
        f[1]=1;
        dist[1]=0;
        int min,minn;
        for(int i=1;i<=n-1;i++){
            min=1000000;
            for(int j=1;j<=n;j++) 
               if(!f[j]&&dist[j]>-1&&dist[j]<min) min=dist[j],minn=j;
            f[minn]=true;
            for(int j=1;j<=n;j++)
             if(!f[j]&&dist[minn]>-1&&mapm[minn][j]>-1&&((dist[j]==-1)||
                (dist[j]>-1&&dist[minn]+mapm[minn][j]<dist[j]))){
                    int z=1;
                 dist[j]=dist[minn]+mapm[minn][j];
             }    
        }
    }
    int main(){
        scanf("%d%d%d",&n,&p,&k);
        for(int i=1;i<=p;i++){
            scanf("%d%d%d",&sz[i].a,&sz[i].b,&sz[i].l);
            map[sz[i].a][sz[i].b]=1;map[sz[i].b][sz[i].a]=1;
            if(sz[i].l>r) r=sz[i].l;
            if(sz[i].l<l) l=sz[i].l;
        }
        int x=1;
        bfs();                              //宽搜解决0和-1的情况; 
        if(a[n]<k&&a[n]!=0){printf("0");return 0;}
        if(a[n]==0) {printf("-1");return 0;}
        while(l<=r){
            mid=(l+r)/2;
            for(int i=1;i<=n;i++)
             for(int j=1;j<=n;j++) mapm[i][j]=-1;
            for(int i=1;i<=p;i++) if(sz[i].l<=mid){//小于mid的忽略,大于mid的设为1; 
                    mapm[sz[i].a][sz[i].b]=0;    
                    mapm[sz[i].b][sz[i].a]=0;
                }
                else{
                    mapm[sz[i].a][sz[i].b]=1;
                    mapm[sz[i].b][sz[i].a]=1;
                }
            for(int i=1;i<=n;i++) f[i]=0,dist[i]=mapm[1][i];
            dj();                                  //找最短路,统计大于mid路的条数; 
            if(dist[n]<=k){ans=mid;r=mid-1;}
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    获取本机IP,用户代理
    10 种机器学习算法的要点(附 Python)(转载)
    怎么查找执行比较慢的sql语句-DBA给的建议
    .net 调度器怎么实现心跳(socket除了他,没选择吧)
    分布式多计算机调度平台
    续【C# 以管理员方式启动Winform,进而使用管理员控制Windows Service】
    C# 以管理员方式启动Winform,进而使用管理员控制Windows Service
    SqlServer2008根据现有表,获取该表的分区创建脚本
    SqlServer常用命令
    创建分区表过程
  • 原文地址:https://www.cnblogs.com/qingang/p/5574287.html
Copyright © 2020-2023  润新知