傳送到Codeforces:0.0spa
板子題,在這裏貼個板子。
這題面是smg?題面中有說每一個點只能通過一次嗎?是我瞎了嗎?
由於這WA on test 27一個小時,煩死了,浪費時間。code
#include <cstring> #include <algorithm> #include <cstdio> #include <queue> #include <cassert> using namespace std; const int MAXN = 1000; const int MAXM = 100000; const int INF = 0x3f3f3f3f; int _w; int read() { int x; _w = scanf( "%d", &x ); return x; } namespace MCMF { struct Edge { int u, v, c, f, w; Edge() {} Edge( int u, int v, int c, int f, int w ): u(u), v(v), c(c), f(f), w(w) {} }; int n, m, s, t; int head[MAXN], nxt[MAXM]; Edge edge[MAXM]; void init( int _n ) { n = _n, m = 0; for( int i = 0; i < n; ++i ) head[i] = -1; } void adde( int u, int v, int c, int w ) { edge[m] = Edge(u, v, c, 0, w); nxt[m] = head[u], head[u] = m++; edge[m] = Edge(v, u, 0, 0, -w); nxt[m] = head[v], head[v] = m++; } queue<int> q; int dis[MAXN], inq[MAXN], res[MAXN], from[MAXN]; bool spfa() { for( int i = 0; i < n; ++i ) dis[i] = INF, inq[i] = 0; dis[s] = 0, inq[s] = 1, q.push(s), res[s] = INF; while( !q.empty() ) { int u = q.front(); q.pop(); inq[u] = 0; for( int i = head[u]; ~i; i = nxt[i] ) { const Edge &e = edge[i]; if( e.c > e.f && dis[u] + e.w < dis[e.v] ) { dis[e.v] = dis[u] + e.w; from[e.v] = i; res[e.v] = min( res[u], e.c-e.f ); if( !inq[e.v] ) inq[e.v] = 1, q.push(e.v); } } } return dis[t] != INF; } void augment() { int f = res[t], u = t; while( u != s ) { int i = from[u]; edge[i].f += f; edge[i^1].f -= f; u = edge[i].u; } } int solve( int _s, int _t ) { s = _s, t = _t; int cost = 0; while( spfa() ) { cost += res[t] * dis[t]; augment(); } return cost; } } int n, k, g[MAXN][MAXN]; int s, t, ss, tt, nid; int in[MAXN], out[MAXN]; void adde( int u, int v, int l, int r, int w ) { MCMF::adde(ss, v, l, 0); MCMF::adde(u, tt, l, 0); MCMF::adde(u, v, r-l, w); } void solve() { s = nid++, t = nid++, ss = nid++, tt = nid++; for( int i = 1; i <= n; ++i ) in[i] = nid++, out[i] = nid++; MCMF::init(nid); adde(t, s, 0, INF, 0); adde(s, out[1], 0, k, 0); for( int i = 2; i <= n; ++i ) { adde(out[i], t, 0, INF, 0); adde(in[i], out[i], 1, 1, 0); // 每一個點只能通過一次 } for( int i = 1; i <= n; ++i ) for( int j = i+1; j <= n; ++j ) adde(out[i], in[j], 0, INF, g[i][j]); printf( "%d\n", MCMF::solve(ss, tt) ); } int main() { n = read()+1, k = read(); for( int i = 1; i <= n; ++i ) for( int j = i+1; j <= n; ++j ) g[i][j] = read(); solve(); return 0; }