BZOJ 1927. [Sdoi2010]星際競速

http://www.lydsy.com/JudgeOnline/problem.php?id=1927
http://hi.baidu.com/lydrainbowcat/item/96ade2bf64c221f363388eb9

Brief description:

略。)

Analysis:

費用流,最小路徑覆蓋。)


//}/* .................................................................................................................................. */

int n, m;

namespace MinCostMaxFlow{

    const int N = 2048, M = 2*N*N + 9;
    const int NN = 2047; // cover_bit(N) - 1

    int D[N], hd[N], suc[M], to[M], cap[M], cst[M];
    int n, m, s, t; LL nesf, flow, cost;

    int new_node(){
        hd[n] = 0;
        return n++;
    }

    inline void add_edge(int x, int y, int c, int w = 0){
        suc[m] = hd[x], to[m] = y, cap[m] = c, cst[m] =  w, hd[x] = m++;
        suc[m] = hd[y], to[m] = x, cap[m] = 0, cst[m] = -w, hd[y] = m++;
        //nesf += w;
    }

    inline void add_edgee(int x, int y, int c, int w = 0){
        add_edge(x, y, c, w);
        add_edge(y, x, c, w);
    }

    int Q[NN+1], pre[N], cz, op; bool inQ[N];

#define v to[i]
#define c cap[i]
#define f cap[i^1]
#define w cst[i]

    bool spfa(){
        fill(inQ, inQ+n, 0), fill(D, D+n, INF);
        cz = 0, op = 1; D[Q[cz] = s] = 0; while (cz != op){
            int u = Q[cz++]; inQ[u] = 0; cz &= NN;
            REP_G(i, u) if (c && checkMin(D[v], D[u]+w)){
                pre[v] = i; if (!inQ[v]) Q[op++] = v, inQ[v] = 1, op &= NN;
            }
        }
        return D[t] != INF;
    }

#undef v

    void add_path(){
        int d = INF; int u, v = t; do{
            int i = pre[v]; checkMin(d, c);
            u = to[i^1], v = u;
        } while (u != s);

        flow += d; u, v = t; do{
            int i = pre[v]; f += d, c -= d; cost += d*w;
            u = to[i^1], v = u;
        } while (u != s);
    }

    pair<LL, LL> Run(){
        cost = 0, flow = 0; while (spfa()) add_path();
        return MP(cost, flow);
    }


#undef c
#undef f
#undef w

    void Init(){

        RST(hd); m = 2; RD(::n, ::m); s = 0, t = 2*::n+1; n = t+1;

        REP_1(i, ::n){
            add_edge(s, ::n+i, 1, RD());
            add_edge(s, i, 1, 0);
            add_edge(::n+i, t, 1, 0);
        }

        DO(::m){
            int x, y, w; RD(x, y, w); if (x > y) swap(x, y);
            add_edge(x, y+::n, 1, w);
        }
    }
} //using namespace MinCostMaxFlow;

int main(){

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif


    MinCostMaxFlow::Init();
    cout << MinCostMaxFlow::Run().fi << endl;
}