IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    BZOJ3118: Orz the MST

    wyfcyx发表于 2015-08-21 18:17:53
    love 0

    题解:

    首先树上的边权只可能减少.非树边上的权值只可能增大.

    然后就有对于一条非树边,修改后的权值要不小于所有它覆盖的树边被修改后的权值.

    注意题目中其实是保证树边数目$\times$非树边数目$\leq{4000}$的.

    然后对偶一下发现有初始可行解,直接上单纯形.

    代码:

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
     
    #define inf 0x3f3f3f3f
    struct Linear_Programming{
        static const int N=4010;
        static const int M=1010;
        int n,m,A[M][N],b[M],c[N],v,B[M],nB[N];
        int _c[N],_v,_nB[N],Bins[N+M],nBins[N+M];
        inline void pivot(int l,int e){
            int i,j;
            for(i=1;i<=n;++i)
                if(i!=e)
                    A[l][i]/=A[l][e];
            b[l]/=A[l][e];
            A[l][e]=1/A[l][e];
            for(i=1;i<=m;++i)
                if(i!=l&&A[i][e]!=0){
                    for(j=1;j<=n;++j)
                        if(j!=e)
                            A[i][j]-=A[i][e]*A[l][j];
                    b[i]-=A[i][e]*b[l];
                    A[i][e]*=-A[l][e];
                }
            for(i=1;i<=n;++i)
                if(i!=e)
                    c[i]-=c[e]*A[l][i];
            v+=c[e]*b[l];
            c[e]*=-A[l][e];
            swap(B[l],nB[e]);
        }
        inline int Simplex(){
            int i,j,l,e,lim;
            while(1){
                for(e=0,i=1;i<=n;++i)
                    if(c[i]>0){
                        e=i;
                        break;
                    }
                if(!e)
                    return v;
                for(lim=inf,i=1;i<=m;++i)
                    if(A[i][e]>0&&lim>b[i]/A[i][e]){
                        l=i;
                        lim=b[i]/A[i][e];
                    }
                if(lim==inf)
                    return inf;
                pivot(l,e);
            }
        }
        inline bool init(){
            int i,j,l,e,min_b=inf;
            for(i=1;i<=m;++i)
                if(b[i]<min_b){
                    min_b=b[i];
                    l=i;
                }
            if(min_b>=0)
                return 1;
            memcpy(_c,c,sizeof c);
            _v=v;
            memcpy(_nB,nB,sizeof nB);
            memset(c,0,sizeof c);
            v=0;
            nB[++n]=0;
            c[n]=-1;
            for(i=1;i<=m;++i)
                A[i][n]=-1;
            pivot(l,n);
            if(Simplex()<0)
                return 0;
            else{
                for(i=1;i<=m;++i)
                    if(B[i]==0){
                        for(j=1;j<=n;++j)
                            if(A[i][j]!=0){
                                pivot(i,j);
                                break;
                            }
                    }
                for(i=1;i<=n;++i)
                    if(nB[i]==0)
                        e=i;
                --n;
                for(i=e;i<=n;++i)
                    nB[i]=nB[i+1];
                for(i=1;i<=m;++i)
                    for(j=e;j<=n;++j)
                        A[i][j]=A[i][j+1];
                memset(c,0,sizeof c);
                v=_v;
                for(i=1;i<=n;++i)
                    nBins[nB[i]]=i;
                for(i=1;i<=m;++i)
                    Bins[B[i]]=i;
                for(i=1;i<=n;++i)
                    if(nBins[_nB[i]])
                        c[nBins[_nB[i]]]+=_c[i];
                    else{
                        v+=_c[i]*b[Bins[_nB[i]]];
                        for(j=1;j<=n;++j)
                            c[j]-=_c[i]*A[Bins[_nB[i]]][j];
                    }
                return 1;
            }
        }
    }g;
     
    #define N 310
    #define M 1010
    int head[N],next[M<<1],end[M<<1],F[M<<1],ind=2;
    inline void addedge(int a,int b,int f){
        int q=ind++;
        end[q]=b;
        next[q]=head[a];
        head[a]=q;
        F[q]=f;
    }
    inline void make(int a,int b,int f){
        addedge(a,b,f);
        addedge(b,a,f);
    }
     
    struct Edge{
        int a,b,c,f,A,B;
        inline void read(){
            scanf("%d%d%d%d%d%d",&a,&b,&c,&f,&A,&B);
        }
    }E[M];
     
    int pa[N],pa_edge[N];
    inline void dfs(int x,int fa){
        for(int j=head[x];j;j=next[j])
            if(end[j]!=fa&&F[j]){
                pa[end[j]]=x;
                pa_edge[end[j]]=j>>1;
                dfs(end[j],x);
            }
    }
     
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("tt.in","r",stdin);
    #endif
     
        int n,m;
        scanf("%d%d",&n,&m);
        int i,j;
        for(i=1;i<=m;++i)
            E[i].read();
        for(i=1;i<=m;++i)
            make(E[i].a,E[i].b,E[i].f);
        int lim=0;
        for(i=1;i<=m;++i)
            if(!E[i].f){
                pa[E[i].a]=0;
                dfs(E[i].a,-1);
                for(j=E[i].b;j!=E[i].a;j=pa[j]){
                    ++lim;
                    g.A[pa_edge[j]][lim]=1;
                    g.A[i][lim]=1;
                    g.c[lim]=E[pa_edge[j]].c-E[i].c;
                }
            }
        for(i=1;i<=m;++i)
            g.b[i]=E[i].f?E[i].B:E[i].A;
        g.n=lim;
        g.m=m;
        for(i=1;i<=g.n;++i)
            g.nB[i]=i;
        for(i=1;i<=g.m;++i)
            g.B[i]=g.n+i;
        g.init();
        cout<<g.Simplex()<<endl;
        return 0;
    }


沪ICP备19023445号-2号
友情链接