zoukankan      html  css  js  c++  java
  • 【利用‘单调性’解决一类二维最优问题】

    例一:CodeForces76A:

    题意: 给定N点M边的无向连通图,每条边有两个权值(g,s)。 给定G,S。 让你给出一组(g0,s0)使得图中仅留下g<=g0, s<=s0的边之后,依然连通,并求G*g0+S*s0的最小值。 n<=200,m<=50000。

    思路:要生成最小生成树,我们选择的边如果按g0递增,那么易得s0递减。 按g0递增,一条条的加边(g<=g0),每次加边,把对应的s加入有序序列中(序列长度为N-1)。 复杂度O(N*M)。

    例二:BZOJ3669:

    题意:给定一个无向图,每条边有两个权值ai和bi,从1走到N,设路径上a权的最大值为A,b权的最大值为B,求A+B的最小值。n<=5*1e4. m<=5*1e4。

    思路:按照例一排序,就是最小生成树了,即对于每个a,找到对应的b下限。但是O(N*M过不了),需要用LCT维护生成树(我也不会)。

    -------------------------------------------2018/4/3--补了LCT,然后回来做第二题。---------------------------------------------------------

    思路:对边按ai排序,然后一条条的加边,如果加边E的时候形成了环,就找环上的最大Maxb权值,如果Maxb大于Eb,则删去Max那条边,新加E边,否则不加。

              同时,如果1和N连通,更新最小值(当前Ea+Maxb)。

     注意:由于LCT一般是针对节点权值,而这里的边权,可以转化一下:加边edge时,改为加两条边:add(edge.a,E) ;add(edge.b,E);

                E点代表原边,范围是[1,M],edge.a代表原点,范围是[M+1,M+N]; 

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=200010;
    const int inf=1000000000;
    struct edge{
        int x,y,a,b;
        bool friend operator <(edge w,edge v){
            return w.a<v.a;
        }
    }e[maxn];
    void read(int &x){
        char c=getchar(); x=0;
        for(;c>'9'||c<'0';c=getchar());
        for(;c<='9'&&c>='0';c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    }
    struct LCT
    {
        int Max[maxn],rev[maxn],ch[maxn][2],fa[maxn],stc[maxn],top;
        int isroot(int x){
            return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
        }
        int get(int x){
            return ch[fa[x]][1]==x;
        }
        void pushdown(int x)
        {
            if(!rev[x]||!x) return ;
            swap(ch[x][0],ch[x][1]);
            if(ch[x][0]) rev[ch[x][0]]^=1; 
            if(ch[x][1]) rev[ch[x][1]]^=1; 
            rev[x]=0;
        }
        void pushup(int x)
        {
            Max[x]=x;
            if(ch[x][0]&&e[Max[ch[x][0]]].b>e[Max[x]].b) Max[x]=Max[ch[x][0]];
            if(ch[x][1]&&e[Max[ch[x][1]]].b>e[Max[x]].b) Max[x]=Max[ch[x][1]];
        }
        void rotate(int x)
        {
            int old=fa[x],fold=fa[old],opt=get(x);
            if(!isroot(old)) ch[fold][get(old)]=x;
            fa[x]=fold;
            ch[old][opt]=ch[x][opt^1]; fa[ch[old][opt]]=old;
            ch[x][opt^1]=old; fa[old]=x; 
            pushup(old); pushup(x);
        }
        void splay(int x)
        {
            int top=0; stc[++top]=x;
            for(int i=x;!isroot(i);i=fa[i]) stc[++top]=fa[i];
            for(int i=top;i;i--) pushdown(stc[i]);
            for(int f;!isroot(x);rotate(x)){
                if(!isroot(f=fa[x]))
                  rotate(get(x)==get(f)?f:x);
            }        
        }
        void access(int x)
        {
            int rson=0;
            for(;x;rson=x,x=fa[x]){
                splay(x);
                ch[x][1]=rson;
                pushup(x);
            }
        }
        int find(int x){ access(x); splay(x); while(ch[x][0]) x=ch[x][0]; return x;}
        int query(int x,int y) { make_root(y); access(x);  splay(x); return Max[x]; }
        void make_root(int x) { access(x); splay(x); rev[x]^=1; }
        void link(int x,int y) { make_root(x); fa[x]=y; splay(x); }
        void cut(int x,int y) { make_root(x); access(y); splay(y); fa[x]=ch[y][0]=0; }    
    }S;
    int main()
    {
        int N,M,i,ans=inf;
        read(N); read(M);
        for(i=1;i<=M;i++){
            read(e[i].x); read(e[i].y); 
            read(e[i].a); read(e[i].b); 
        }
        sort(e+1,e+M+1);
        for(i=1;i<=M;i++){
            if(S.find(M+e[i].x)!=S.find(M+e[i].y)) {
                 S.link(i,M+e[i].x);
                 S.link(i,M+e[i].y);
            }
            else{
                int tmp=S.query(M+e[i].x,M+e[i].y);
                if(e[tmp].b>e[i].b) {
                    S.cut(tmp,M+e[tmp].x); S.cut(tmp,M+e[tmp].y);
                    S.link(i,M+e[i].x); S.link(i,M+e[i].y);
                }
            }
            if(S.find(M+1)==S.find(M+N)){
                int tmp=S.query(M+1,M+N);
                if(e[tmp].b+e[i].a<ans) ans=e[tmp].b+e[i].a;
            }
        }
        if(ans==inf) ans=-1;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    .NetCore使用protobuf 生成C#代码(Grpc)
    备忘:.net WebServices 禁用浏览器访问与禁用wsdl生成
    Java web中的web-xml中标签定义之jsp-config
    转:centos7.2安装jdk1.6和/etc/profile不生效问题
    转:Linux中tomcat服务成功发布但局域网浏览器无法访问
    windows10(本机)与VirtualBox中CentOS7(虚拟机)互相访问总结
    获取JPEGImageEncoder和JPEGCode这两个类
    WebService发布与调用问题:expected: {http://schemas.xmlsoap.org/soap/envelope/}Envelope but found: {http://schemas.xmlsoap.org/wsdl/}definitions
    转:问题解决:The project cannot be built until build path errors are resolved
    利用Metaweblog技术的API接口同步到多个博客网站(详细)
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8665998.html
Copyright © 2011-2022 走看看