codevs 3336 电话网络 SPFA 解题报告

本文介绍了一种利用最短路径算法解决地震灾区电话线路重建问题的方法。通过二分查找确定最优成本,确保从已接入网络的起始杆到目标杆能够成功连接,同时考虑了限定的总成本。
摘要由CSDN通过智能技术生成

题目描述 Description

由于地震使得连接汶川县城电话线全部损坏,假如你是负责将电话线接到震中汶川县城的负责人,汶川县城周围分布着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

输入描述 Input Description

输入文件的第一行包含三个用空格隔开的整数:N,P和K。

第二行到第P+1行:每行分别都为空格隔开的整数:Ai,Bi和Li。

输出描述 Output Description

输出文件中仅包含一个整数,表示在这项工程上的最小支出。如果任务不可能完成,则输出-1。

样例输入 Sample Input

5 7 1

1 2 5

3 1 4

2 4 8

3 2 3

5 2 9

3 4 7

4 5 6

样例输出 Sample Output

4

思路

根据题目描述,我们可以很容易的得出这道题需用最短路算法。
关于k的取值,我们可以二分。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1000000+5;
int n,m,k,num,head[N],dis[N],flag[N];
queue<int>q;
struct edge
{
    int u,v,w;
    int next;
}ed[N];
void build(int u,int v,int w)
{
    ed[++num].u=u;
    ed[num].v=v;
    ed[num].w=w;
    ed[num].next=head[u];
    head[u]=num;
}
void SPFA(int s)
{
    memset(flag,0,sizeof(flag));
    memset(dis,inf,sizeof(dis));
    dis[1]=0;flag[1]=0;
    q.push(1);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();flag[u]=0;
        for (int i=head[u];i;i=ed[i].next)
        {
            int now,v=ed[i].v;
            if (ed[i].w<=s) now=0;
            else now=1;
            if (dis[v]>dis[u]+now)
            {
                dis[v]=dis[u]+now;
                if (flag[v]==0)
                {
                    q.push(v);
                    flag[v]=1;
                }
            }
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        build(x,y,z);
        build(y,x,z);
    }
    int l=0,r=N,ans=-1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        SPFA(mid);
        if (dis[n]<=k) {ans=mid;r=mid-1;}
        else l=mid+1;
    }
    printf("%d",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值