时间限制: 1000 ms 内存限制: 65536 KB
提交数: 581 通过数: 307
【题目描述】
原题来自:USACO 2008 Jan. Silver

在郊区有 N 座通信基站,P 条双向电缆,第 i 条电缆连接基站 Ai​和 Bi​​ 。特别地,1 号基站是通信公司的总站,N 号基站位于一座农场中。现在,农场主希望对通信线路进行升级,其中升级第 i 条电缆需要花费 Li​ 。

电话公司正在举行优惠活动。农场主可以指定一条从 1 号基站到 N 号基站的路径,并指定路径上不超过 K 条电缆,由电话公司免费提供升级服务。农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。求至少用多少钱能完成升级。

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

【输入】
第一行三个整数 N,P,K;

接下来 P 行,每行三个整数 Ai,Bi,Li.

【输出】
若不存在从 1 到 N 的路径,输出 −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
【提示】
数据范围:

0≤K<N≤1000,1≤P≤2000

#include <iostream>
#include <cstring>
#include <cstdlib>
#define N 2048
#define INF 0x3f3f3f3f
using namespace std;

int GN;
int dis[N];
bool ved[N];
int m,n;
int K;

int maxv;    //存放最大价值 

inline void init()
{
    memset(G,0x3f,sizeof(G));
    
    cin.tie(0);
    cin>>n>>m>>K;
    
    if(m==0)
    {
        cout<<-1<<endl;
        exit(0);
    }
    
    for(int i=1;i<=m;i++)
    {
        int f,t,d;cin>>f>>t>>d;
        if(Gf>d)
        {
            Gf=Gt=d;
            maxv=max(Gf,maxv);
        }
    }
}

inline bool guess(int mid)
{
    memset(dis,0x3f,sizeof(dis));
    memset(ved,0,sizeof(ved));
    
    for(int i=1;i<=n;i++)
        if(G1!=INF)    
        {
            if(G1>mid)
                dis[i]=1;
            else 
                dis[i]=0;
        }
    
    dis[1]=0;
    ved[1]=true;
    
    for(int k=1;k<n;k++)
    {
        int add=0,minn=INF;
        for(int i=1;i<=n;i++)
            if(!ved[i] && dis[i]<minn)
            {
                add=i;
                minn=dis[i];
            }
        ved[add]=true;
        
        for(int i=1;i<=n;i++)
            if(!ved[i] && Gadd!=INF)
                dis[i]=min(dis[i],dis[add]+((Gadd>mid)?(1):(0)));    
    }
    
    
    
    if(dis[n]==INF)    //不存在该道路 
    {
        cout<<-1<<endl;
        exit(0);
    }
    
    
    return dis[n]<=K;
}

int main()
{
    init();
    int l=0,r=maxv+1;
    while(l<=r)
    {
        if(guess((l+r)/2))
            r=(l+r)/2-1;
        else
            l=(l+r)/2+1;
    }
    cout<<l<<endl;
    return 0;
}

Last modification:February 7th, 2021 at 02:00 pm