AOJ 2290: Attack the Moles
ブログに記事を書きます Advent Calendar 2014 - Adventar7日目。
最小費用流はBellman-Fordを1回やって流量くらいの回数Dijkstraをするらしい。
また、Bellman-Fordはうまくトポロジカル順に行うとよい。
と、最小費用流に関する理解を深めた(といいたいが、いまだに仕組みをわかっていない)
#include<stdio.h> #include<string.h> #include<vector> #include<queue> #include<algorithm> using namespace std; namespace MCF { // required <string.h> <vector> <queue> <algorithm> #define MAXN 6100 #define MAXM 21000000 #define wint int #define cint int const wint wEPS = 0; const wint wINF = 1001001001; const cint cEPS = 0; const cint cINF = 1001001001; int n, m, ptr[MAXN], next[MAXM], zu[MAXM]; wint capa[MAXM], tof; cint cost[MAXM], toc, d[MAXN], pot[MAXN]; int vis[MAXN], pree[MAXN]; void init(int _n) { n = _n; m = 0; memset(ptr, ~0, n * 4); } void ae(int u, int v, wint w, cint c) { next[m] = ptr[u]; ptr[u] = m; zu[m] = v; capa[m] = w; cost[m] = +c; ++m; next[m] = ptr[v]; ptr[v] = m; zu[m] = u; capa[m] = 0; cost[m] = -c; ++m; } bool solve(int src, int ink, wint flo = wINF) { int i, u, v; wint f; cint c, cc; memset(pot, 0, n * sizeof(cint)); for (bool cont = 1; cont; ) { cont = 0; for (u = 0; u < n; ++u) for (i = ptr[u]; ~i; i = next[i]) if (capa[i] > wEPS) { if (pot[zu[i]] > pot[u] + cost[i] + cEPS) { pot[zu[i]] = pot[u] + cost[i]; cont = 1; } } } for (toc = 0, tof = 0; tof + wEPS < flo; ) { typedef pair<cint,int> node; priority_queue< node,vector<node>,greater<node> > q; for (u = 0; u < n; ++u) { d[u] = cINF; vis[u] = 0; } for (q.push(make_pair(d[src] = 0, src)); !q.empty(); ) { c = q.top().first; u = q.top().second; q.pop(); if (vis[u]++) continue; for (i = ptr[u]; ~i; i = next[i]) if (capa[i] > wEPS) { cc = c + cost[i] + pot[u] - pot[v = zu[i]]; if (d[v] > cc + cEPS) { q.push(make_pair(d[v] = cc, v)); pree[v] = i; } } } if (!vis[ink]) return 0; f = flo - tof; for (v = ink; v != src; v = zu[i ^ 1]) { i = pree[v]; f=min(f,capa[i]); } for (v = ink; v != src; v = zu[i ^ 1]) { i = pree[v]; capa[i] -= f; capa[i ^ 1] += f; } tof += f; toc += f * (d[ink] - pot[src] + pot[ink]); for (u = 0; u < n; ++u) pot[u] += d[u]; } return 1; } } int x[3100]; int t[3100]; int p[3100]; pair<int,pair<int,int> > in[3100]; int ABS(int a){return max(a,-a);} int main(){ int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); int s=2*a; int sl=2*a+1; int sr=2*a+2; int T=2*a+3; int U=T+1; int V=U+1; MCF::init(V+1); // MCF::ae(U,s,2,0); // MCF::ae(T,V,2,0); MCF::ae(s,T,2,0); MCF::ae(s,sl,1,0); MCF::ae(s,sr,1,0); int val=0; for(int i=0;i<a;i++){ scanf("%d%d%d",x+i,t+i,p+i); in[i]=make_pair(t[i],make_pair(x[i],p[i])); } std::sort(in,in+a); for(int i=0;i<a;i++){ t[i]=in[i].first; x[i]=in[i].second.first; p[i]=in[i].second.second; } for(int i=0;i<a;i++){ if(ABS(x[i]-c)<=t[i]*b)MCF::ae(sl,2*i,1,0); if(ABS(x[i]-d)<=t[i]*b)MCF::ae(sr,2*i,1,0); MCF::ae(2*i+1,T,1,0); /* MCF::ae(U,i*2+1,1,0); MCF::ae(i*2,V,1,0); MCF::ae(i*2+1,i*2,1,p[i]);*/ MCF::ae(i*2,i*2+1,1,-p[i]); val-=p[i]; // MCF::ae(2*i,2*i+1,1,-p[i]); } for(int i=0;i<a;i++){ for(int j=0;j<a;j++){ if(t[i]<t[j]&&(t[j]-t[i])*b>=ABS(x[i]-x[j])){ // printf("%d %d\n",i,j); MCF::ae(i*2+1,j*2,1,0); } } } MCF::solve(s,T,2+a); printf("%d\n",-MCF::toc); }