SSl2267 2013年全国信息学分区联赛普级组day1 货车运输(rmq)

来源:互联网 发布:中国人 知乎 编辑:程序博客网 时间:2024/05/21 11:37

2013年全国信息学分区联赛普级组day1 货车运输

Description

这里写图片描述
这里写图片描述

分析:由最小生成树的性质显然可得这题是最大生成树然后在树上两点之间找到最小限重,最小限重可以用rmq求。

代码

#include <cstdio>#include <algorithm>#define maxn 60000using namespace std;struct arr{    int x,y,w;}b[maxn];struct edge{    int to,nxt,w;}a[maxn];int n,m,l,ans;int fa[maxn],ls[maxn],dep[maxn];int f[maxn][20],dis[maxn][20];bool v[maxn];int so(arr p,arr q){    return p.w>q.w;}int find(int x){    if (fa[x]==x) return x;    return fa[x]=find(fa[x]);}void add(int p,int q,int z){    a[++l].to=q;    a[l].w=z;    a[l].nxt=ls[p];    ls[p]=l;}void mst(){    sort(b+1,b+m+1,so);    for (int i=1;i<=n;i++)        fa[i]=i;    for (int i=1;i<=m;i++)    {        int u=find(b[i].x);        int v=find(b[i].y);        if (u!=v)        {            fa[u]=v;            add(b[i].x,b[i].y,b[i].w);            add(b[i].y,b[i].x,b[i].w);        }    }}void dfs(int s,int far){    v[s]=true;    dep[s]=dep[far]+1;    for (int i=ls[s];i;i=a[i].nxt)        if (!v[a[i].to])        {            f[a[i].to][0]=s;            dis[a[i].to][0]=a[i].w;            dfs(a[i].to,s);        }}int min(int x,int y){    return x<y?x:y;}void lca(int p,int q){    if (dep[p]<dep[q])    {        p^=q;q^=p;p^=q;    }    for (int i=19;i>=0;i--)        if (dep[q]<=dep[f[p][i]]&&f[p][i]!=0)        {            ans=min(ans,dis[p][i]);            p=f[p][i];        }    if (p==q) return;    for (int i=19;i>=0;i--)        if (f[p][i]!=f[q][i])        {            ans=min(min(dis[p][i],dis[q][i]),ans);            p=f[p][i];            q=f[q][i];        }    ans=min(min(dis[p][0],dis[q][0]),ans);    return;}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=m;i++)        scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].w);    mst();    for (int j=0;j<20;j++)        for (int i=1;i<=n;i++)            dis[i][j]=123456789;    for (int i=1;i<=n;i++)        if (!v[i]) dfs(i,0);    for (int j=1;j<20;j++)        for (int i=1;i<=n;i++)        {            f[i][j]=f[f[i][j-1]][j-1];            dis[i][j]=min(dis[i][j-1],dis[f[i][j-1]][j-1]);        }    int q;    scanf("%d",&q);    for (int i=1;i<=q;i++)    {        int x,y;        scanf("%d%d",&x,&y);        if (find(x)!=find(y)) printf("%d\n",-1);            else            {                ans=123456789;                lca(x,y);                printf("%d\n",ans);            }    }}
阅读全文
0 0
原创粉丝点击