(最短路+二分)4919: [Usaco2009 Jan]Telephone Lines

4919: [Usaco2009 Jan]Telephone Lines

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 5  Solved: 3
[Submit][Status][Web Board]

Description

在郊区有N座通信基站,P条双向电缆,第 i 条电缆连接基站 A_i 和 B_i。特别地,1号基站是通信公司的总站,N
号基站位于一座农场中。现在,农场主希望对通信线路进行升级,其中升级第 i 条电缆需要花费 L_i。电话公司
正在举行优惠活动。农场主可以指定一条从1号基站到N号基站的路径,并指定路径上不超过K条电缆,由电话公司
免费提供升级服务。农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。求至少用
多少钱能完成升级。
0≤K<N≤1000,1≤P≤10000。

Input

Output

HINT

Source

求k+1大边的最大值最小

最短路+二分

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

struct my{
    int v;
    int next;
    int w;
};

const int maxn=1000+10;
const int nil=(1<<29);
int n,fa,m,k,fa2;
int d[maxn],vis[maxn];
int adj[maxn];
int adj2[maxn];
my bian2[maxn*20];
my bian[maxn*20];

void myinsert(int u,int v,int w){
     bian[++fa].v=v;
     bian[fa].w=w;
     bian[fa].next=adj[u];
     adj[u]=fa;
}

void myinsert2(int u,int v,int w){
     bian2[++fa2].v=v;
     bian2[fa2].w=w;
     bian2[fa2].next=adj2[u];
     adj2[u]=fa2;
}

bool spfa(int x){
     queue<int>q;
     memset(vis,false,sizeof(vis));
     for (int i=1;i<=n;i++) d[i]=nil;
     d[x]=0;
     q.push(x);
     vis[x]=true;
     while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=false;
        for (int i=adj[u];i;i=bian[i].next){
            int v=bian[i].v;
            if(d[u]<nil&&d[v]>d[u]+bian[i].w){
                d[v]=d[u]+bian[i].w;
                if(!vis[v]){
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
     }
     return d[n]<=k;
}

bool check(int p){
     for (int i=1;i<=n;i++){
        for (int j=adj2[i];j;j=bian2[j].next){
            if(bian2[j].w<=p) bian[j].w=0;
            else bian[j].w=1;
        }
     }
     return spfa(1);
}

int main(){
    int ans=-1,l=0,r=0;
    int u,v,w;
   scanf("%d%d%d",&n,&m,&k);
    fa=0;
    fa2=0;
    for (int i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        myinsert(u,v,w);
        myinsert(v,u,w);
        myinsert2(u,v,w);
        myinsert2(v,u,w);
        r=max(w,r);
    }
    while(l<=r){
        int mid=(l+r)/2;
        if(check(mid)){
            ans=mid;
            r=mid-1;
        }
        else {
            l=mid+1;
        }
    }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/lmjer/p/8633333.html