BZOJ1937 / BZOJ 3118(单纯形)

传送门

题解:
KM?网络流建模?不存在的。
单纯形立水之。
(注意对偶之后跑得更快,取反大概要慢8倍)。

BZOJ3118:

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;

const int RLEN=1<<18|1;
inline char nc() {
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
    char ch=nc(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
    return i*f;
}

const int N=3e2+50, M=1e3+50;
int n,m,fa[N],dep[N],fm[N];
struct data {
    int u,v,w,f,a,b;
    data() {}
    data(int u,int v,int w,int f,int a,int b) : u(u), v(v), w(w), f(f), a(a), b(b) {}
} edge[M];
vector <pii> g[N];

namespace LP {
    int n,m,q[4005],p;
    double a[M][4005];
    const double eps=1e-7;
    const double INF=1e15;
    inline void pivot(int l,int e) {
        double t=a[l][e]; a[l][e]=1;
        for(int i=0;i<=n;i++) a[l][i]/=t;
        p=0; for(int i=0;i<=n;i++) if(fabs(a[l][i])>eps) q[++p]=i;
        for(int i=0;i<=m;i++) if(i!=l && fabs(a[i][e])>eps) {
            double t=a[i][e]; a[i][e]=0;
            for(int j=1;j<=p;j++) a[i][q[j]]-=t*a[l][q[j]];
        }
    }
    inline void init() {
        while(true) {
            int l=0, e=0;
            for(int i=1;i<=m;i++)
                if(a[i][0]<-eps && (!l || (rand()%2))) l=i;
            if(!l) return;
            for(int i=1;i<=n;i++)
                if(a[l][i]<-eps && (!e || (rand()%2))) e=i;
            if(!e) {puts("Infeasible"); return;}
            pivot(l,e);
        }
    }
    inline void simplex() {
        while(true) {
            int l=0, e=0;
            for(int i=1;i<=n;i++)
                if(a[0][i]>eps) {e=i; break;}
            if(!e) return;
            double mn=INF;
            for(int i=1;i<=m;i++)
                if(a[i][e]>eps && mn>a[i][0]/a[i][e])
                    mn=a[i][0]/a[i][e], l=i;
            if(!l) {puts("Unbounded"); return;}
            pivot(l,e);
        }
    }
    inline void add(int x,int y) {
        ++n; 
        a[x][n]=1;
        a[y][n]=1;
        a[0][n]=edge[x].w-edge[y].w;
    }
    inline void solve() {
        init(); simplex();
        cout<<(long long)(-a[0][0]+0.5);
    }
}

inline void dfs(int x,int f) {
    fa[x]=f; dep[x]=dep[f]+1;
    for(int e=g[x].size()-1;e>=0;e--) {
        int v=g[x][e].first; if(v==f) continue;
        fm[v]=g[x][e].second; dfs(v,x);
    }
}

inline int lca(int x,int y) {
    while(x^y) 
        (dep[x]<dep[y]) ? y=fa[y] : x=fa[x];
    return x;
}

inline void group(int x,int l,int id) {while(x^l) LP::add(fm[x],id), x=fa[x];}

int main() {
    n=rd(), m=rd();
    for(int i=1;i<=m;i++) {
        int x=rd(), y=rd(), w=rd(), f=rd(), a=rd(), b=rd();
        if(f) g[x].push_back(pii(y,i)), g[y].push_back(pii(x,i)), LP::a[i][0]=b;
        else LP::a[i][0]=a;
        edge[i]=data(x,y,w,f,a,b);
    } dfs(1,0); LP::n=0; LP::m=m;
    for(int i=1;i<=m;i++) {
        if(edge[i].f) continue;
        int x=edge[i].u, y=edge[i].v;
        int l=lca(x,y);
        group(x,l,i); group(y,l,i);
    } LP::solve();
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/81004159