BZOJ3118php
少有的單純形好題啊
咱們先抽離出生成樹
生成樹中的邊只可能減,其它邊只可能加
對於不在生成樹的邊,其權值必定要比生成樹中其端點之間的路徑上全部的邊都大
而後就是一個最小化的線性規劃
爲了防止限制過多
咱們只需對原先生成樹中的比該邊大的邊創建限制便可
而後就是單純形 + 對偶ios
雙倍經驗ui
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<cmath> #include<map> #define LL long long int #define REP(i,n) for (int i = 1; i <= (n); i++) #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt) #define cls(s,v) memset(s,v,sizeof(s)) #define mp(a,b) make_pair<int,int>(a,b) #define cp pair<int,int> using namespace std; const int maxn = 1005,maxm = 10005,NN = 1005; const double eps = 1e-10,INF = 1e15; inline int read(){ int out = 0,flag = 1; char c = getchar(); while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();} while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();} return flag ? out : -out; } int h[maxn],ne = 1; struct EDGE{int to,nxt,id;}ed[maxn << 1]; inline void build(int u,int v,int id){ ed[++ne] = (EDGE){v,h[u],id}; h[u] = ne; ed[++ne] = (EDGE){u,h[v],id}; h[v] = ne; } int n,m,N,M; int dep[maxn],fa[maxn],id[maxn]; int U[NN],V[NN],W[NN],F[NN],A[NN],B[NN]; double a[maxn][maxm]; void dfs(int u){ Redge(u) if ((to = ed[k].to) != fa[u]){ fa[to] = u; dep[to] = dep[u] + 1; id[to] = ed[k].id; dfs(to); } } void Pivot(int l,int e){ double t = a[l][e]; a[l][e] = 1; for (int j = 0; j <= n; j++) a[l][j] /= t; for (int i = 0; i <= m; i++) if (i != l && fabs(a[i][e]) > 0){ t = a[i][e]; a[i][e] = 0; for (int j = 0; j <= n; j++) a[i][j] -= a[l][j] * t; } } void simplex(){ while (true){ int l = 0,e = 0; double mn = INF; for (int j = 1; j <= n; j++) if (a[0][j] > eps){e = j; break;} if (!e) break; for (int i = 1; i <= m; i++) if (a[i][e] > eps && a[i][0] / a[i][e] < mn) mn = a[i][0] / a[i][e],l = i; Pivot(l,e); } } int main(){ N = read(); M = read(); REP(i,M){ U[i] = read(); V[i] = read(); W[i] = read(); F[i] = read(); A[i] = read(); B[i] = read(); if (F[i]) build(U[i],V[i],i); } dfs(1); n = M; REP(i,M){ if (F[i]) a[i][0] = B[i]; else{ a[i][0] = A[i]; int u = U[i],v = V[i],x; while (u != v){ if (dep[u] < dep[v]) swap(u,v); x = id[u]; if (W[x] > W[i]){ m++; a[x][m] = a[i][m] = 1; a[0][m] = W[x] - W[i]; } u = fa[u]; } } } swap(n,m); simplex(); printf("%.0lf\n",-a[0][0]); return 0; }