P2245 星际导航

题目描述

sideman 做好了回到Gliese星球的硬件准备,但是sideman的导航系统还没有完全设计好。为了方便起见,

我们可以认为宇宙是一张有N 个顶点和M 条边的带权无向图,顶点表示各个星系,两个星系之间有边就表示两个星系之间可以直航,

而边权则是航行的危险程度。

sideman 现在想把危险程度降到最小,具体地来说,就是对于若干个询问(A,B),sideman 想知道从顶点A

航行到顶点B 所经过的最危险的边的危险程度值最小可能是多少。作为 sideman的同学,你们要帮助sideman

返回家园,兼享受安全美妙的宇宙航行。所以这个任务就交给你了。

输入输出格式

输入格式:

第一行包含两个正整数N和M,表示点数和边数。

之后M行,每行三个整数A,B和L,表示顶点A和B之间有一条边长为L的边。顶点从1开始标号。

下面一行包含一个正整数Q,表示询问的数目。

之后Q行,每行两个整数 A和B,表示询问A和B之间最危险的边危险程度的可能最小值。

输出格式:

对于每个询问, 在单独的一行内输出结果。如果两个顶点之间不可达, 输出impossible。

输入输出样例

输入样例#1: 
4 5
1 2 5
1 3 2
2 3 11
2 4 6
3 4 4
3
2 3
1 4
1 2
输出样例#1: 
5
4
5

说明

对于 40%的数据,满足 N≤1000,M≤3000,Q≤1000

对于 80%的数据,满足 N≤10000,M≤105,Q≤1000

对于 100% 的数据,满足 N≤105,M≤3×105,Q≤105,L≤109,数据不保证没有重边和自环。

代码

kruskal重构树裸题,做法同货车运输

最危险的边危险程度的可能最小值,也就是最大值最小

我们边权按升序排序,val[lca(x,y)]即为答案

#include<bits/stdc++.h>
using namespace std;
const int maxn=200000+100,maxm=200000+100,md=20+5;
int head[maxn],val[maxn],f[maxn],dep[maxn],lg[maxn]; 
int ff[maxn][md];
int size=0,cnt=0;
struct tree
{
    int to,next;
}e[maxm<<1];
struct edge
{
    int u,v,val;
}E[maxm<<1];
int n,m;
void init()
{
    for(int i=1;i<=n;i++)
    f[i]=i;
}
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
void addedge(int u,int v)
{
    e[++size].to=v;e[size].next=head[u];head[u]=size;
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
bool cmp(const edge&a,const edge&b)
{
    return a.val>b.val;
}
void kruskal()
{
    for(int i=1;i<=m;i++)
    {
        int u=E[i].u,v=E[i].v;
        int fu=find(u),fv=find(v);
        if(fu!=fv)
        {
        cnt++;
        f[cnt]=f[fu]=f[fv]=cnt;
        val[cnt]=E[i].val;
        addedge(cnt,fu);addedge(fu,cnt);
        addedge(fv,cnt);addedge(cnt,fv);
        }

    }
}
void dfs(int u,int fa)
{
    dep[u]=dep[fa]+1;
    ff[u][0]=fa;
    for(int i=1;i<=lg[dep[u]];i++)
    ff[u][i]=ff[ff[u][i-1]][i-1];
    for(int i=head[u];i;i=e[i].next)
    {
        int to=e[i].to;
        if(to==fa)continue;
        dfs(to,u);
    }
}
int lca(int x,int y)
{
    if(dep[x]<dep[y])
    swap(x,y);
    while(dep[x]>dep[y])
    x=ff[x][lg[dep[x]-dep[y]]];
    if(x==y)
    return x;
    for(int i=lg[dep[x]];i>=0;i--)
    if(ff[x][i]!=ff[y][i])x=ff[x][i],y=ff[y][i];
    return ff[x][0];
}
int main()
{
    n=read(),m=read();cnt=n;
    init();
    for(int i=1;i<=m;i++)
    E[i].u=read(),E[i].v=read(),E[i].val=read();
    sort(E+1,E+1+m,cmp);
    kruskal();
    for(int i=1;i<=n;i++)
    lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);
    for(int i=1;i<=cnt;i++)
    if(!dep[i])
    dfs(find(i),0); 
    int k=read();
    for(int i=1;i<=k;i++)
    {
        int x=read(),y=read();
        if(find(x)!=find(y))printf("-1\n");
        else printf("%d\n",val[lca(x,y)]);
    }
    return 0;
}
View Code

 

 

posted @ 2019-05-05 17:41  DriverBen  阅读(190)  评论(0编辑  收藏  举报