笨笨的电话网络

笨笨的电话网络

题目描述

多年以后,笨笨长大了,成为了电话线布置师。由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人。该市周围分布着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\n",ans);
    return 0;
}

时间: 2024-10-27 12:59:07

笨笨的电话网络的相关文章

笨笨熊搬家交通篇

笨笨熊要搬家,它现在的家在B点,新的豪宅在H点,现在要从B点到H点 地图R表示行,C表示列,其中: -表示能通过 #表示不能通过 B表示笨笨熊原来的家 H表示笨笨熊的新豪宅 输入 R C R×C矩阵 输出 Y//表示可以通过 N//表示不可以通过 #include <iostream> #include <queue> using namespace std; //Point in the grid typedef struct { int x; int y; }Pos; //re

jquery开发的”天才笨笨碰“游戏

前段时间湖南卫视的快乐大本营里有一款“天才笨笨碰”游戏非常火.这款游戏主要是考选手的声母联想词语的能力. 小篇在看完这个节目后用jquery制作了“天才笨笨碰”网页游戏.先上效果图: 游戏规则: 1.如图点击开始,系统会给中间五个小块随机分配五个声母(哈哈,这边可能有些网友已经忘记声母都有哪些了.声母一共有23个:b p m f d t n l g k h j q x zh ch sh r z c s y w) 2.两位选手用这五个声母来联想词语,或句子.把含声母的色块推到对方那一边就胜利了(注

笨笨熊搬家打包篇

笨笨熊搬家打包篇 描述:  森林里的笨笨熊今天可开心啦——他买了新房子,乔迁新喜要搬家了.因此,笨笨熊请了许多好朋友来帮忙搬家,并准备了很多小纸盒用来装需要搬的物品,不过,这些纸盒的容积都是相同的,并且最多只能装两个物品.但是,为了不打扰太多的朋友,笨笨熊想了个“聪明”办法:让每个纸盒使用效率最高(注:只要纸盒容积大于物品的体积之和就认为可以装下:物品体积不会大于纸盒容积),这样需要的纸盒最少.为了帮助笨笨熊提前通知朋友,请你根据笨笨熊的办法,帮忙算出:需要纸盒的最少数目是多少?        

IO-08. 输出倒三角图案(for循环写的不符合,用笨笨的println,%&gt;_&lt;%)

本题要求编写程序,输出指定的由“*”组成的倒三角图案. 输入格式:本题目没有输入. 输出格式:按照下列格式输出由“*”组成的倒三角图案. * * * * * * * * * *注意:严格按照下面截图的样式. 无奈用for循环写不出,只好用笨笨的println一行行的输出了. public class Main { public static void main(String[] args) { System.out.println("* * * *"); System.out.prin

20190817笨笨的套题

题 A \(DHOJ 1503\) 笨笨与电影票 B \(DHOJ 1506\) 笨笨玩糖果 C \(DHOJ 1506\) 笨笨玩糖果 正解 求出哪些是必胜态还是必败态 胜利要尽量快,失败要尽量慢 显而易见这道题是有一个博弈的背景的,那么根据博弈的那两个经典结论,只要能转移到一个必败态的就是必胜态,如果一个必败态都转移不到的就是比败态. 那么我们首先将0与1初始化为必败态,对于每一个数i,减去所有比i小的所有质数,如果有必败态即为必胜态,如果都转移不到就是必败态了. 接着再留心一下题目,题目要

【数学】Vijos P1582 笨笨的L阵游戏

题目链接: https://vijos.org/p/1582 题目大意: 就是o(o<=50)个人在n*m(n,m<=2000)的格子上放L型的东西(有点像俄罗斯方块的L,可对称旋转),问第几个人覆盖全图或无解. 题目思路: [数学] n*m%8如果为0则(n*m/4-1)%o+1那个人胜利. 否则无解. (当时手画了大概8以内的几种样例,就感觉好像有规律可循,慢慢推但是感觉可能有错,于是偷偷瞄了一眼别人的题解,果然是规律题.但是我并不会证明.) 1 // 2 //by coolxxx 3 /

python 中的特殊方法,纠正自己笨笨的记忆

1. __new__ 和 __init__ 的区别 python 2.x 老式类(默认继承type) class A: pass 老式类中没有__new__类方法(也就是说定义也不会执行,它不是老式类的类方法),__Init__ 作为构造函数,创建实例对象,并初始化. 过程: 类 => __init__() => 实例(self)创建并初始化 __init__: 不能有返回值 python 3 和 python 2.x(显示继承新式类) class A(object): pass 注: 在Py

NOIP200805 笨小猴(低效算法)(一大桶水)【A006】

[A006]笨小猴[难度A]—————————————————————————————————————————————————————————————— [题目要求] 笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼.但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小猴就认为这是个Lucky Word,

09day1

词编码 模拟 [问题描述] 一个发送机可以通过一条隧道发送一些以二进制代码组成的单词.在其尽头的接受机可以使用特殊技术恢复到最初的单词.每个单词最初都由0和1组成.所有的单词最初长度都为n(4<=n<=1000).当穿过隧道之后单词可能发生以下几种情况之一: (1)任意(一个)0 被 1 取代: (2)任意(一个)符号被删除: (3)一个符号(0 或 1)被插入到任何位置: (4)不改变. 我们知道最初的单词都具有以下性质:有 1 的位置号的总和是 n+1 的倍数,或者是 0. [输入] n