UVA 11354 Bond

来源:互联网 发布:网络言情小说作家 编辑:程序博客网 时间:2024/05/22 13:38

UVA 11354 Bond

最小生成树,LCA,ST

题目

给出一张n个点m条边的无向图, 每条边有一个危险度,有q个询问, 每次给出两个点s、t,找一条路, 使得路径上的最大危险度最小。

思路

首先,我们可以发现,如果求一个最小生成树, 那么任意两点, 在生成树上有唯一路径, 而且这条路径上的最大危险值一定最小。
然后在最小生成树上做路径最小值的询问,处理出LCA,在用RMQ。

代码

#include<bits/stdc++.h>#include<stdlib.h>#define M(a,b) memset(a,b,sizeof(a))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int MAXN=100007;typedef long long LL;struct Edge{    int from,to;    LL cost;    Edge(){}    Edge(int from,int to,LL cost){this->from=from,this->to=to,this->cost=cost;}    bool operator< (const Edge& a)const    {        return cost<a.cost;    }} e[MAXN<<1];vector<Edge> nG[MAXN];int father[MAXN];void init(int n){    for(int i=1; i<=n; i++)    {        father[i]=i;    }}int find(int x){    if(father[x]==x) return x;    else    {        return father[x]=find(father[x]);    }}void merge(int x, int y){    int fx=father[x], fy=father[y];    if(fx!=fy) father[fx]=fy;}void kruskal(int n,int m){    sort(e+1,e+2*m+1);init(n);    int cnt=0;    for(int i=1;i<=n;i++)    {        nG[i].clear();    }    for(int i=1; i<=2*m; i++)    {        Edge te=e[i];        if(find(te.from)!=find(te.to))        {            merge(te.from, te.to);            nG[te.from].push_back(Edge(te.from,te.to,te.cost));            nG[te.to].push_back(Edge(te.to,te.from,te.cost));            cnt++;        }        if(cnt==n-1)        {            break;        }    }}int parent[30][MAXN],depth[MAXN];LL dis[30][MAXN];//LCAvoid dfs(int v, int f, int d){    parent[0][v] = f;    dis[0][v] = -1;    depth[v] = d;    for(int i=0; i<nG[v].size(); i++)    {        Edge nv = nG[v][i];        if(nv.to!=f)            dfs(nv.to, v, d+1);        else            dis[0][v] = nv.cost;    }}void init_lca(int n){    memset(dis, 0, sizeof dis);    memset(depth, -1, sizeof depth);    for(int i=1; i<=n; i++)        if(depth[i]<0)            dfs(i, -1, 0);    for(int k=0; k+1<30; k++)    {        for(int i=1; i<=n; i++)        {            if(parent[k][i]<0) parent[k+1][i] = dis[k+1][i] = -1;            else            {                parent[k+1][i] = parent[k][parent[k][i]];                dis[k+1][i] = max(dis[k][i], dis[k][parent[k][i]]);            }        }    }}LL lca(int u, int v){    if(depth[v] > depth[u]) swap(u, v);    LL ret = 0;    for(int i=0; i<30; i++){        if((depth[u]-depth[v]) >> i & 1) {            ret = max(ret, dis[i][u]);            u = parent[i][u];        }    }    if(u==v) return ret;    for(int i=30-1; i>=0; i--){        if(parent[i][u]!=parent[i][v]){            ret = max(ret, dis[i][u]);            ret = max(ret, dis[i][v]);            u = parent[i][u];v = parent[i][v];        }    }    ret = max(ret, dis[0][u]);    ret = max(ret, dis[0][v]);    return ret;}int main(){    int n,m;int cas=0;    while(scanf("%d%d",&n,&m)==2)    {        for(int i=1; i<=2*m; i+=2)        {            int a,b;            LL c;            scanf("%d%d%lld",&a,&b,&c);            e[i].from=a,e[i].to=b,e[i].cost=c;            e[i+1].from=b,e[i+1].to=a,e[i+1].cost=c;        }        kruskal(n,m);        init_lca(n);        int q;scanf("%d",&q);        if(cas==0) cas=1;        else printf("\n");        while(q--)        {            int a,b;scanf("%d%d",&a,&b);            printf("%lld\n",lca(a,b));        }    }    return 0;}
原创粉丝点击