电话网络

Posted CaptainLi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了电话网络相关的知识,希望对你有一定的参考价值。

[题目描述]
由于地震使得连接汶川县城电话线全部损坏,假如你是负责将电话线接到震中汶川县城的负责人,汶川县
城周围分布着 N(1≤N≤1,000)根按 1..N 顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相
连。一共 P(1≤P≤10,000)对电话线杆间可以拉电话线,其余的由于地震使得无法被连接。
第 i 对电话线杆的两个端点分别为 Ai,Bi,它们间的距离为 Li(1≤Li≤1,000,000)。数据中保证每对
(Ai,Bi)最多只出现 1 次。编号为 1 的电话线杆已经接人了全国的电话网络,整个县城的电话线全都连到了编
号为 N 的电话线杆上。也就是说,你的任务仅仅是找一条将 1 号和 N 号电话线杆连起来的路径,其余的电话线
杆并不一定要连人电话网络。
电信公司决定支援灾区免费为汶川县城连结 K(0≤K<N)对由你指定的电话线杆。对于此外的那些电话线,需要
为它们付费,总费用等于其中最长的电话线的长度(每根电话线仅连接一对电话线杆)。如果需要连接的电话线
杆不超过 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

这个题怎么做?初看感觉好像没有任何思路。当时因为要求最小值,那么就想到了二分答案这样一种方法。但是当时没有想到的是如何二分,如果直接跑最短路显然不行,但是我们可以跑的是最短路上有多少条比当前二分的值边权大的边。直接对每一条边赋值即可,如果边权大于当前二分的值就赋为1否则为0,之后把这个当边权跑最短路即可。这样的话,我们就不停的二分答案就好了。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar(‘\n‘)
#define inf 2147483647
using namespace std;
typedef long long ll;
const int M = 100005;
int n,p,k,a,b,c,head[M],dis[M],cnt,r = M*10,l;
bool vis[M],flag,pd[M];
queue <int> q;
struct node
{
    int to,next,v,w;
}e[M];
inline int read()
{
    int as = 0,fu = 1;
    char c = getchar();
    while(c < 0 || c > 9)
    {
        if(c == -) fu = -1;
        c = getchar();
    }
    while(c >= 0 && c <= 9)
    {
        as = as * 10 + c - 0;
        c = getchar();
    }
    return as * fu;
}

void add(int x,int y,int z)
{
    e[++cnt].to = y;
    e[cnt].v = z;
    e[cnt].next = head[x];
    head[x] = cnt;
}

void spfa(int s)
{
    dis[s] = 0,vis[s] = 0;q.push(s);
    while(!q.empty())
    {
        int now = q.front();q.pop(),vis[now] = 0;
        for(int i = head[now];i;i = e[i].next)
        {
            if(dis[now] + e[i].w < dis[e[i].to])
            {
                dis[e[i].to] = dis[now] + e[i].w;
                if(!vis[e[i].to]) q.push(e[i].to),vis[e[i].to] = 1;
            }
        }
    }
}
int main()
{
    freopen("phone.in","r",stdin);
    freopen("phone.out","w",stdout);
    n = read(),p = read(),k = read();
    rep(i,1,p) 
    {
        a = read(),b = read(),c = read();
        add(a,b,c);
        add(b,a,c);
    }
    while(l < r)
    {
        int mid = (l+r) >> 1;
        rep(i,1,cnt) 
        {
            if(e[i].v > mid) e[i].w = 1;
            else e[i].w = 0;    
        }
        rep(i,1,n) dis[i] = inf;
        spfa(1);
        if(dis[n] == inf) printf("-1\n"),exit(0);
//        printf("%d %d\n",mid,dis[n]);
        if(dis[n] > k) l = mid + 1;
        else r = mid;
    }
    printf("%d\n",l);
    return 0;
}

 

以上是关于电话网络的主要内容,如果未能解决你的问题,请参考以下文章

Android开发常用代码片段

VSCode自定义代码片段14——Vue的axios网络请求封装

VSCode自定义代码片段14——Vue的axios网络请求封装

VSCode自定义代码片段14——Vue的axios网络请求封装

firebase 的短信代码不匹配

十个html5代码片段,超实用,一定要收藏