「USACO08JAN」电话线Telephone Lines 解题报告

题面

大意:在加权无向图上求出一条从 \(1\) 号结点到 \(N\) 号结点的路径,使路径上第 \(K + 1\) 大的边权尽量小。

思路:

由于我们只能直接求最短路,不能记录过程中的具体的边——那样会特别麻烦

所以,我们就尝试着去想更优的办法

题目中所说,能够免去 \(K\) 条边的费用,那么对于要建设的边中,肯定免去费用最大 $K $ 条边更优

我们关注的应该是第 \(K+1\) 大边的边权,因为其他边权大于这条边边权的边都会被略去

这条边可以枚举吗?

似乎不行,枚举的复杂度还要在最短路的基础上,乘上一个 \(M\) ,不就TLE(Time Limit Enough)了吗……

那么——对于这个边的边权,能不能二分呢?

首先,二分需要满足单调性

题目中,这条第 \(K+1\) 大的边边权越小,能够满足的情况越少,反之亦然

因此我们可以使用二分的方法来查找答案

怎么判断满足或不满足

对于边权大于 \(mid\) 的边,我们改变它的边权为1,否则为0,然后再跑最短路,这样得出来的结果应该是从 \(1\) 号结点到 $N $ 号结点至少要有几条大于 \(mid\) 的边,然后与 \(K\) 比较,小于 \(K\) 则满足,否则不满足

Code:

#include<bits/stdc++.h>
#define INF 0x7f7f7f7f
#define M 10010
#define N 1010
using namespace std;
struct node{
    int to,cost;
    int nxt;
    node(int a,int b):to(a),cost(b){    }
    node(){ }
}b[M<<1];
int head[N],d[N],vis[N];
int n,m,res,t,ans=INF;//初值一样要为INF
int read()
{
    int s=0;
    char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c))
    {
        s=(s<<1)+(s<<3)+c-'0';
        c=getchar();
    }
    return s;
}
void add(int x,int y,int cost)//建边,正反一起
{
    b[++t]=node(y,cost);
    b[t].nxt=head[x];
    head[x]=t;
    b[++t]=node(x,cost);
    b[t].nxt=head[y];
    head[y]=t;
    return;
}
bool BFS(int k)//好吧,这里不算严格的最短路,因为边权变成了0和1,可以直接宽搜搞定,但是下面的程序,
{//明明是一个真SPFA,假宽搜
    int i,to,cur,cost;
    for(i=1;i<=n;i++)
    {
        d[i]=INF;
        vis[i]=0;
    }
    queue<int>p;
    p.push(1);
    vis[1]=1;
    d[1]=0;
    while(!p.empty())
    {
        cur=p.front();p.pop();
        vis[cur]=0;
        for(i=head[cur];i;i=b[i].nxt)
        {
            to=b[i].to;
            cost=d[cur]+(b[i].cost>k);//处理边权
            if(cost<d[to])
            {
                d[to]=cost;
                if(!vis[to])
                {
                    vis[to]=1;
                    p.push(to);
                }
            }
        }
    }
    if(d[n]<=res)//判断
        return 1;
    return 0;
}
int main()
{
    int i;
    int x,y,cost;
    int l,r,mid;
    n=read();m=read();res=read();
    l=r=0;
    for(i=1;i<=m;i++)
    {
        x=read();y=read();cost=read();
        add(x,y,cost);//建边,注意是双向的
        r=max(r,cost);//r的上限,可以自己赋为1e6,这是题目中给的最大值
    }
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(BFS(mid))//判断
        {
            ans=mid;
            r=mid-1;
        }
        else
            l=mid+1;
    }
    if(ans==INF)//初值应该为INF,不能为0,因为有可能电信公司比较大方,免费之类的——给我多好
        ans=-1;
    printf("%d",ans);
    return 0;
}

另外提供一个比较high的评测

在洛谷过了,这里不一定过哦!

原文地址:https://www.cnblogs.com/hovny/p/10237742.html

时间: 2024-11-09 02:09:30

「USACO08JAN」电话线Telephone Lines 解题报告的相关文章

「P5004」专心OI - 跳房子 解题报告

题面 把\(N\)个无色格子排成一行,选若干个格子染成黑色,要求每个黑色格子之间至少间隔\(M\)个格子,求方案数 思路: 矩阵加速 根据题面,这一题似乎可以用递推 设第\(i\)个格子的编号为\(i\),有\(i\)个格子时的方案数为\(f(i)\) 显然,当 \(i \le M+1\) 时, 可以所有格子不染色(方案数为\(1\)种,或者最多有一个格子染色(方案数为\(i\)种) 所以有\(f(i)=i+1\) 当\(i>M+1\)时, 对于第\(i\)个格子可以由第\(i-1\)个格子转移

洛谷 P1948 [USACO08JAN]电话线Telephone Lines

P1948 [USACO08JAN]电话线Telephone Lines 题目描述 Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of the cables required to connect his farm to the phone system. There a

P1948 [USACO08JAN]电话线Telephone Lines

P1948 [USACO08JAN]电话线Telephone Lines 题目描述 多年以后,笨笨长大了,成为了电话线布置师.由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人.该市周围分布着N(1<=N<=1000)根据1--n顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有p(1<=p<=10000)对电话杆可以拉电话线.其他的由于地震使得无法连接. 第i对电线杆的两个端点分别是ai,bi,它们的距离为li(1<=li<=1000000)

【洛谷P1948】[USACO08JAN]电话线Telephone Lines

题目描述 Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of the cables required to connect his farm to the phone system. There are N (1 ≤ N ≤ 1,000) forlorn telephon

[USACO08JAN]电话线Telephone Lines

题目描述 Farmer John wants to set up a telephone line at his farm. Unfortunately, the phone company is uncooperative, so he needs to pay for some of the cables required to connect his farm to the phone system. There are N (1 ≤ N ≤ 1,000) forlorn telephon

题解 guP1948 【[USACO08JAN]电话线Telephone Lines】

二分+dij题目 首先读一遍题目,一定要仔细读(不要问我为什么,我就是受害者qwq 你会发现最终的费用是由最长的电话线决定的,而非电话线长度和. 至此就有了一个基本思路--枚举(二分)出可能的最长电话线长度,然后对其进行dij判断. dij思路如下: 1.已知枚举出了假定答案ans: 2.在最短路过程中,判断有多少条线长度大于ans,并将其免费: 3.最后判断免费条数,若大于给出的t即不可行,反之可行. 开long long!!! 代码: #include<bits/stdc++.h> usi

P1948 [USACO08JAN]电话线Telephone Lines spfa 二分答案

多年以后,笨笨长大了,成为了电话线布置师.由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人.该市周围分布着N(1<=N<=1000)根据1……n顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有p(1<=p<=10000)对电话杆可以拉电话线.其他的由于地震使得无法连接. 第i对电线杆的两个端点分别是ai,bi,它们的距离为li(1<=li<=1000000).数据中每对(ai,bi)只出现一次.编号为1的电话杆已经接入了全国的电话网络,整个

「csp校内训练 2019-10-24」解题报告

「csp校内训练 2019-10-24」解题报告 T1.猴猴吃苹果 \(Description\) 猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有 \(N \ (N \leq 50000)\) 个苹果,每个苹果有一个编号,分别为 \(0\) ~ \(N - 1\) 它们之间由 \(N-1\) 个树枝相连,猴猴可以从树枝的一端爬到树枝的另一端,所以猴猴可以从任意一个苹果的位置出发爬到任意猴猴想去的苹果的位置. 猴猴开始在编号为 \(K \ (K < N)\) 的苹果的位置,并且把这个苹果吃

「csp校内训练 2019-10-30」解题报告

「csp校内训练 2019-10-30」解题报告 T1.树 题目链接(逃) \(Description\): 现在有一棵树,共 \(N\) 个节点. 规定:根节点为 \(1\) 号节点,且每个节点有一个点权. 现在,有 \(M\) 个操作需要在树上完成,每次操作为下列三种之一: \(1 \ x \ a\):操作 \(1\),将节点 \(x\) 点权增加 \(a\). \(2 \ x \ a\):操作 \(2\),将以节点 \(x\) 为根的子树中所有点的权值增加 \(a\). \(3 \ x\)