loj #136. 最小瓶颈路

 

#136. 最小瓶颈路

 

题目描述

给定一个包含 n nn 个节点和 m mm 条边的图,每条边有一个权值。
你的任务是回答 k kk 个询问,每个询问包含两个正整数 s ss 和 t tt 表示起点和终点,要求寻找从 s ss 到 t tt 的一条路径,使得路径上权值最大的一条边权值最小。

输入格式

第一行包含三个整数 n nn、m mm、k kk,分别表示 n nn 个节点, m mm 条路径, k kk 个询问。 接下来 m mm 行,每行三个整数 u uu , v vv , w ww, 表示一个由 u uu 到 v vv 的长度为 w ww 的双向边。 再接下来 k kk行,每行两个整数 s ss , t tt,表示询问从 s ss 连接到 t tt 的所有路径中单边长度最大值的最小值。

输出格式

输出包含 k kk 行,每一行包含一个整数 p pp 。p pp 表示 s ss 连接到 t tt 的所有路径中单边长度最大值的最小值。另外,如果 s ss 到 t tt 没有路径相连通,输出 -1 即可。

样例

样例输入

8 11 3
1 2 10
2 5 50
3 4 60
7 5 60
3 6 30
1 5 30
6 7 20
1 7 70
2 3 20
3 5 40
2 6 90
1 7
2 8
6 2

样例输出

30
-1
30

数据范围与提示

对于 30% 30\%30% 的数据 n≤100,m≤1000,k≤100,w≤1000 n \leq 100, m \leq 1000, k \leq 100, w \leq 1000n100,m1000,k100,w100
对于 70% 70\%70% 的数据 n≤1000,m≤10000,k≤1000,w≤100000 n \leq 1000, m \leq 10000, k \leq 1000, w \leq 100000n1000,m10000,k1000,w10000
对于 100% 100\%100% 的数据 n≤1000,m≤100000,k≤1000,w≤10000000 n \leq 1000, m \leq 100000, k \leq 1000, w \leq 10000000n1000,m100000,k1000,w1000000
本题可能会有重边。
为了避免 Special Judge,本题所有的 w ww 均不相同。

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1010
using namespace std;
int head[maxn],num,n,m,s,t,q,mx,mn=0x7fffffff;
bool vis[maxn];
struct node{int to,pre,v;}e[200010];
void Insert(int from,int to,int v){
    e[++num].to=to;
    e[num].v=v;
    e[num].pre=head[from];
    head[from]=num;
}
bool check(int limit){
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(s);vis[s]=1;
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=head[now];i;i=e[i].pre){
            if(e[i].v>limit)continue;
            int to=e[i].to;
            if(!vis[to]){
                if(to==t)return 1;
                vis[to]=1;q.push(to);
            }
        }
    }
    return vis[t];
}
int qread(){
    int i=0,j=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
    return i*j;
}
int main(){
    n=qread();m=qread();q=qread();
    int x,y,z;
    for(int i=1;i<=m;i++){
        x=qread();y=qread();z=qread();
        Insert(x,y,z);Insert(y,x,z);
        mn=min(mn,z);mx=max(mx,z);
    }
    while(q--){
        s=qread();t=qread();
        int l=mn,r=mx,ans=-1;
        if(!check(mx)){puts("-1");continue;}
        if(s==t){puts("0");continue;}
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid))r=mid-1,ans=mid;
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
}
81分 二分答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1010
using namespace std;
int n,m,k,head[maxn],num,fa[maxn][21],dis[maxn][21],dep[maxn];
int f[maxn];
bool vis[maxn];
struct Node{
    int u,v,w;
    bool operator < (const Node &b)const{
        return w<b.w;
    }
}E[100010];
struct node{int to,pre,v;}e[maxn*2];
void Insert(int from,int to,int v){
    e[++num].to=to;
    e[num].v=v;
    e[num].pre=head[from];
    head[from]=num;
}
int find(int x){
    if(x==f[x])return x;
    return f[x]=find(f[x]);
}
void dfs(int x,int father){
    fa[x][0]=father;
    dep[x]=dep[father]+1;
    vis[x]=1;
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(to==father)continue;
        dis[to][0]=e[i].v;
        dfs(to,x);
    }
}
int lca(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    int delta=dep[x]-dep[y];
    int res=0;
    for(int i=0;i<=18;i++)
        if(delta&(1<<i)){
            res=max(res,dis[x][i]);
            x=fa[x][i];
        }
    for(int i=18;i>=0;i--)
        if(fa[x][i]!=fa[y][i]){
            res=max(res,dis[x][i]);
            res=max(res,dis[y][i]);
            x=fa[x][i];y=fa[y][i];
        }
    if(x==y)return res;
    res=max(res,dis[x][0]);
    res=max(res,dis[y][0]);
    return res;
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)f[i]=i;
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);
    sort(E+1,E+m+1);
    for(int i=1;i<=m;i++){
        int f1=find(E[i].u),f2=find(E[i].v);
        if(f1!=f2){
            f[f1]=f2;
            Insert(E[i].u,E[i].v,E[i].w);
            Insert(E[i].v,E[i].u,E[i].w);
        }
    }
    for(int i=1;i<=n;i++)
        if(!vis[i])dfs(i,0);
    for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++){
            fa[i][j]=fa[fa[i][j-1]][j-1];
            dis[i][j]=max(dis[i][j-1],dis[fa[i][j-1]][j-1]);
        }
    while(k--){
        int s,t;
        scanf("%d%d",&s,&t);
        if(find(s)!=find(t)){
            puts("-1");
            continue;
        }
        printf("%d\n",lca(s,t));
    }
}
100分 最小生成树+lca

 

posted @ 2018-04-14 20:30  Echo宝贝儿  阅读(456)  评论(0)    收藏  举报