zoukankan      html  css  js  c++  java
  • BZOJ1050 HAOI2006旅行(最小生成树+LCT)

      暴力枚举路径中权值最小边是哪个,然后求出边权不小于它的边的最小生成树,即可保证该路径上最大值最小。暴力当然可以过,这里使用LCT维护。注意数据中有自环。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 510
    #define M 5010
    #define lson tree[k].ch[0]
    #define rson tree[k].ch[1]
    #define lself tree[tree[k].fa].ch[0]
    #define rself tree[tree[k].fa].ch[1]
    int n,m,s,t,ansx,ansy,v[N+M];
    struct edge
    {
        int x,y,z;
        bool operator <(const edge&a) const
        {
            return z<a.z;
        }
    }e[M];
    struct data{int ch[2],fa,rev,x;
    }tree[N+M];
    void up(int k)
    {
        tree[k].x=k;
        if (v[tree[lson].x]>v[tree[k].x]) tree[k].x=tree[lson].x;
        if (v[tree[rson].x]>v[tree[k].x]) tree[k].x=tree[rson].x;
    }
    void rev(int k){if (k) swap(lson,rson),tree[k].rev^=1;}
    void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;}
    bool isroot(int k){return lself!=k&&rself!=k;}
    int whichson(int k){return rself==k;}
    void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
    void move(int k)
    {
        int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
        if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
        tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa;
        tree[fa].fa=k,tree[k].ch[!p]=fa;
        up(fa),up(k);
    }
    void splay(int k)
    {
        push(k);
        while (!isroot(k))
        {
            int fa=tree[k].fa;
            if (!isroot(fa))
                if (whichson(k)^whichson(fa)) move(k);
                else move(fa);
            move(k);
        }
    }
    void access(int k){for (int t=0;k;t=k,k=tree[k].fa) splay(k),tree[k].ch[1]=t,up(k);}
    void makeroot(int k){access(k),splay(k),rev(k);}
    int findroot(int k){access(k),splay(k);for (;lson;k=lson) down(k);splay(k);return k;}
    void link(int x,int y){makeroot(x);tree[x].fa=y;}
    void cut(int x,int y){makeroot(x);access(y);splay(y);tree[y].ch[0]=tree[x].fa=0;up(y);}
    int query(int x,int y){makeroot(x);access(y);splay(y);return tree[y].x;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj1050.in","r",stdin);
        freopen("bzoj1050.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=m;i++)
        e[i].x=read(),e[i].y=read(),e[i].z=read();
        s=read(),t=read();
        sort(e+1,e+m+1);
        ansx=1000000000,ansy=1;
        for (int i=1;i<=n;i++) v[i]=-1;
        for (int i=1;i<=m;i++) v[i+n]=e[i].z;
        for (int i=m;i;i--)
        if (e[i].x!=e[i].y)
        {
            if (findroot(e[i].x)==findroot(e[i].y))
            {
                int x=query(e[i].x,e[i].y);
                cut(x,e[x-n].x),cut(x,e[x-n].y);
            }
            link(i+n,e[i].x),link(i+n,e[i].y);
            if (findroot(s)==findroot(t))
            {
                int x=v[query(s,t)];
                if (1ll*x*ansy<1ll*ansx*e[i].z) ansx=x,ansy=e[i].z;
            }
        }
        if (ansx==1000000000) cout<<"IMPOSSIBLE";
        else if (ansx%ansy==0) cout<<ansx/ansy;
        else cout<<ansx/gcd(ansx,ansy)<<'/'<<ansy/gcd(ansx,ansy);
        return 0;
    }
  • 相关阅读:
    [原]OpenGL基础教程(四)VBO+纹理绘制四边形
    [原]OpenGL基础教程(二)多边形绘制
    [原]OpenGL基础教程(一)多边形绘制
    [原]VS2012编译GLEW 1.11
    [原]pomelo基础知识(一)
    数据挖掘算法之k-means算法
    送上今年微软的一道笔试题
    数据挖掘算法之决策树算法
    编程之美系列03
    编程之美系列02
  • 原文地址:https://www.cnblogs.com/Gloid/p/9627330.html
Copyright © 2011-2022 走看看