Bond UVA

来源:互联网 发布:信用卡代办软件 编辑:程序博客网 时间:2024/06/01 14:36

Bond UVA - 11354

题目大意:

n个点m条边的图,q次询问,找到一条从s到t的一条边,使所有边的最大危险系数最小。

题解:

使最大的危险系数尽量小,答案一定是最小生成树上的边。
为了快速回答询问,用LCA倍增法记录s和t到他们最近公共祖先的最大值。

Code:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define D(x) cout<<#x<<" = "<<x<<"  "#define E cout<<endlusing namespace std;const int N = 100005;const int M = 500005;int n,m;int pa[N][21],dep[N],mx[N][21];struct Edge{    int u,v,next,w;    Edge(){}    Edge(int _u,int _v,int _w){        u=_u; v=_v; w=_w;    }    bool operator < (const Edge & tp) const {        return w < tp.w;    }}e[N*2],edge[M];int head[N],ec,edgecnt;void clearEdge(){ memset(head,0,sizeof(head)); ec=0; edgecnt=0; }void add(int a,int b,int w){    //D(a); D(b); D(w); E;    ec++; e[ec].u=a; e[ec].v=b; e[ec].w=w;    e[ec].next=head[a]; head[a]=ec;}struct UNSet{    int pa[N];    void init(int n){ for(int i=1;i<=n;i++)pa[i]=i; }    int find(int x){        if(pa[x]!=x) pa[x]=find(pa[x]);        return pa[x];    }} unset;void clearAll(){    clearEdge();    memset(pa,-1,sizeof(pa));    memset(dep,0,sizeof(dep));    memset(mx,-1,sizeof(mx));}void kruskal(){    sort(edge+1,edge+1+edgecnt);    unset.init(n); int cnt=0;    for(int i=1;i<=edgecnt;i++){        int x=unset.find(edge[i].u);         int y=unset.find(edge[i].v);        if(x!=y){            unset.pa[x]=y;            add(edge[i].u,edge[i].v,edge[i].w);            add(edge[i].v,edge[i].u,edge[i].w);            if(++cnt==n-1) break;        }    }}void dfs(int u){    for(int i=head[u];i;i=e[i].next){        int v=e[i].v;        if(v==pa[u][0]) continue;        pa[v][0]=u; dep[v]=dep[u]+1; mx[v][0]=e[i].w;        dfs(v);    }}void init(){    for(int j=1;j<20;j++){        for(int i=1;i<=n;i++){            pa[i][j]=pa[pa[i][j-1]][j-1];            mx[i][j]=max(mx[i][j-1],mx[pa[i][j-1]][j-1]);        }    }}int query(int a,int b){    int ans=-1;    if(dep[a]<dep[b]) swap(a,b);    int cha=dep[a]-dep[b];    for(int j=0;(1<<j)<=cha;j++){        if(cha&(1<<j)){    //忘了这个,WA了一节课QwQ            ans=max(ans,mx[a][j]);            a=pa[a][j];        }    }    if(a!=b){        for(int j=20-1;j>=0;j--){            if(pa[a][j]!=pa[b][j]){                ans=max(ans,max(mx[a][j],mx[b][j]));                a=pa[a][j]; b=pa[b][j];            }        }        ans=max(ans,max(mx[a][0],mx[b][0]));    //Take care!    }    return ans;}int main(){    freopen("a.in","r",stdin);    int a,b,w,q;    int cas=0;    while(~scanf("%d%d",&n,&m) && (n||m)){        if(cas)puts(""); cas++;        clearAll();        for(int i=1;i<=m;i++){            scanf("%d%d%d",&a,&b,&w);            edge[++edgecnt]=Edge(a,b,w);        }        kruskal();        dfs(1);        init();        scanf("%d",&q);        for(int i=1;i<=q;i++){            scanf("%d%d",&a,&b);            printf("%d\n",query(a,b));        }    }}
原创粉丝点击