Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize("Ofast,unroll-loops,inline,omit-frame-pointer,no-asynchronous-unwind-tables,fast-math")
- #pragma GCC target("tune=native,avx,avx2,fma")
- #define WITHOUT_LI 1
- #ifdef CP_GEN
- #define INCLUDE #include
- INCLUDE <algorithm>
- INCLUDE <chrono>
- INCLUDE <cinttypes>
- INCLUDE <cstring>
- INCLUDE <iostream>
- INCLUDE <memory>
- INCLUDE <queue>
- INCLUDE <set>
- INCLUDE <stdio.h>
- INCLUDE <tuple>
- INCLUDE <vector>
- INCLUDE <cmath>
- #else
- #include <algorithm>
- #include <stdio.h>
- #include <vector>
- #include <queue>
- #include <cinttypes>
- #include <chrono>
- #include <tuple>
- #include <iostream>
- #include <memory>
- #include <cstring>
- #include <set>
- #include <cmath>
- #endif
- using namespace std;
- #include "macros.h"
- #include "types.h"
- #include "util.h"
- #include "pdqsort.h"
- #include "random.h"
- #ifdef CP_GEN
- INCLUDE <windows.h>
- #endif
- ld getTime() {
- #ifndef CP_GEN
- return 1.0 * clock() / CLOCKS_PER_SEC;
- #else
- HANDLE hProcess;
- hProcess = GetCurrentProcess();
- FILETIME CreationTime, ExitTime, KernelTime, UserTime;
- GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime);
- uint64_t kernel = ((uint64_t)KernelTime.dwHighDateTime << 32) | KernelTime.dwLowDateTime;
- uint64_t user = ((uint64_t) UserTime.dwHighDateTime << 32) | UserTime.dwLowDateTime;
- return (kernel + user) / 1e7;
- #endif
- }
- using vd = vector<ld>;
- using vvd = vector<vd>;
- const ld EPS = 1e-9;
- struct LPSolver {
- int m, n;
- vi N, B;
- vvd D;
- LPSolver(const vvd &A, const vd &b, const vd &c) :
- m(b.size()), n(c.size()), N(n + 1), B(m), D(m + 2, vd(n + 2)) {
- for (int i = 0; i < m; i++)
- for (int j = 0; j < n; j++) D[i][j] = A[i][j];
- for (int i = 0; i < m; i++)
- { B[i] = n + i; D[i][n] = -1; D[i][n + 1] = b[i]; }
- for (int j = 0; j < n; j++)
- { N[j] = j; D[m][j] = -c[j]; }
- N[n] = -1; D[m + 1][n] = 1;
- }
- void Pivot(int r, int s) {
- static tuple<int, ld> L[100000], R[100000];
- int nl = 0, nr = 0;
- ld inv = 1.0 / D[r][s];
- { for (int i = 0; i < m + 2; i++) if (i != r && (ld)abs((ld)D[i][s]) > EPS) {
- L[nl++] = mt(i,D[i][s]);
- }
- for (int j = 0; j < n + 2; j++) if (j != s && (ld)abs((ld)D[r][j]) > EPS) {
- R[nr++] = mt(j,D[r][j]);
- }
- FOR(j,nr) FOR(i,nl) {
- D[get<0>(L[i])][get<0>(R[j])] -= get<1>(L[i]) * get<1>(R[j]) * inv;
- }
- }
- // the previous block is a (usually) more efficient version of~:
- // for (int i = 0; i < m + 2; i++) if (i != r)
- // for (int j = 0; j < n + 2; j++) if (j != s)
- // D[i][j] -= D[r][j] * D[i][s] * inv;
- for (int j = 0; j < n + 2; j++) if (j != s) D[r][j] *= inv;
- for (int i = 0; i < m + 2; i++) if (i != r) D[i][s] *= -inv;
- D[r][s] = inv;
- swap(B[r], N[s]);
- }
- bool Simplex(int phase) {
- int x = phase == 1 ? m + 1 : m;
- while (true) {
- int s = -1;
- for (int j = 0; j <= n; j++) {
- if (phase == 2 && N[j] == -1) continue;
- if (s == -1 || D[x][j] < D[x][s] ||
- (D[x][j] == D[x][s] && N[j] < N[s])) s = j;
- }
- if (D[x][s] > -EPS) return true;
- int r = -1;
- for (int i = 0; i < m; i++) {
- if (D[i][s] < EPS) continue;
- if (r == -1 || D[i][n + 1] / D[i][s] < D[r][n + 1] / D[r][s] ||
- ((D[i][n + 1] / D[i][s]) == (D[r][n + 1] / D[r][s]) &&
- B[i] < B[r])) r = i;
- }
- if (r == -1) return false;
- Pivot(r, s);
- }
- }
- ld Solve(vd &x) {
- int r = 0;
- for (int i = 1; i < m; i++) if (D[i][n + 1] < D[r][n + 1]) r = i;
- if (D[r][n + 1] < -EPS) {
- Pivot(r, n);
- if (!Simplex(1) || D[m + 1][n + 1] < -EPS)
- return -numeric_limits<ld>::infinity();
- for (int i = 0; i < m; i++) if (B[i] == -1) {
- int s = -1;
- for (int j = 0; j <= n; j++)
- if (s == -1 || D[i][j] < D[i][s] ||
- (D[i][j] == D[i][s] && N[j] < N[s])) s = j;
- Pivot(i, s);
- }
- }
- if (!Simplex(2)) return numeric_limits<ld>::infinity();
- x = vd(n);
- for (int i = 0; i < m; i++) if (B[i] < n) x[B[i]] = D[i][n + 1];
- return D[m][n + 1];
- }
- };
- const int MAXN = 2000;
- const int MAXT = 1000;
- const int MAXX = 101;
- const int MAXP = 7;
- const int infty = 1<<28;
- int n;
- int sx, sy;
- struct location {
- int x, y, p;
- int duration;
- int from, to;
- int score;
- int sdist;
- void read(){
- cin>>x>>y>>duration>>p>>from>>to;
- to -= duration;
- init();
- }
- void init() {
- score = duration * p * (p+5);
- sdist = dist(sx,sy);
- }
- inline int dist(location const& o) const {
- return abs(x-o.x) + abs(y-o.y);
- }
- inline int dist(int x_, int y_) const {
- return abs(x-x_) + abs(y-y_);
- }
- };
- struct MaxFlow {
- struct Edge {
- li from, to, cap, flow, index;
- Edge() = default;
- Edge(li from, li to, li cap, li flow, li index) :
- from(from), to(to), cap(cap), flow(flow), index(index) {}
- };
- li N;
- int ng[2+2*MAXN];
- Edge G[2+2*MAXN][2+2*MAXN];
- li excess[2+2*MAXN];
- li dist[2+2*MAXN];
- li active[2+2*MAXN];
- li count[4+4*MAXN];
- queue<li> Q;
- MaxFlow() { }
- void reset() {
- N = 0;
- Q = queue<li>();
- }
- li addNode() {
- ng[N] = 0;
- excess[N] = 0;
- dist[N] = 0;
- active[N] = 0;
- count[2*N] = 0;
- count[2*N+1] = 0;
- N += 1;
- return N-1;
- }
- li addEdge(li from, li to, li cap, li flow = 0) {
- li ix = ng[from];
- G[from][ng[from]++] = Edge(from, to, cap, flow, ng[to] + (from == to ? 1 : 0));
- G[to][ng[to]++] = Edge(to, from, 0, -flow, ix);
- return ix;
- }
- void enqueue(li v) {
- if (!active[v] && excess[v] > 0) {
- active[v] = true;
- Q.push(v);
- }
- }
- void push(Edge &e) {
- li amt = min(excess[e.from], e.cap - e.flow);
- if(dist[e.from] <= dist[e.to] || amt == 0) return;
- e.flow += amt;
- G[e.to][e.index].flow -= amt;
- excess[e.to] += amt;
- excess[e.from] -= amt;
- enqueue(e.to);
- }
- void gap(li k) {
- FOR(v, N) {
- if(dist[v] < k) continue;
- count[dist[v]]--;
- dist[v] = max(dist[v], N+1);
- count[dist[v]]++;
- enqueue(v);
- }
- }
- void relabel(li v) {
- count[dist[v]]--;
- dist[v] = 2*N;
- FOR(i,ng[v]) if(G[v][i].cap - G[v][i].flow > 0) {
- dist[v] = min(dist[v], dist[G[v][i].to] + 1);
- }
- count[dist[v]]++;
- enqueue(v);
- }
- void discharge(li v) {
- for(li i = 0; excess[v] > 0 && i < (li)ng[v]; ++i) push(G[v][i]);
- if(excess[v] > 0) {
- if(count[dist[v]] == 1) {
- gap(dist[v]);
- } else {
- relabel(v);
- }
- }
- }
- li flow(li s, li t) {
- count[0] = N-1;
- count[N] = 1;
- dist[s] = N;
- active[s] = active[t] = true;
- FOR(i,ng[s]) {
- excess[s] += G[s][i].cap;
- push(G[s][i]);
- }
- while (!Q.empty()) {
- li v = Q.front();
- Q.pop();
- active[v] = false;
- discharge(v);
- }
- li totflow = 0;
- FOR(i,ng[s]) totflow += G[s][i].flow;
- return totflow;
- }
- };
- const li INF = (1<<28);
- li ha[MAXN+16][MAXN+16];
- int u[MAXN+16+1], v[MAXN+16+1], p[MAXN+16+1], way[MAXN+16+1];
- int minv[MAXN+16+1], used[MAXN+16+1];
- // Returns the minimum cost maximum matching
- // !!! !!!
- // !!! Hangs when n > m !!!
- // !!! Transpose the matrix if needed !!!
- // !!! !!!
- vi hungarian(li n, li m) {
- memset(u,0,(n+1)*sizeof(int));
- memset(v,0,(m+1)*sizeof(int));
- memset(p,0,(m+1)*sizeof(int));
- memset(way,0,(m+1)*sizeof(int));
- FORU(i,1,n) {
- p[0] = i;
- li j0 = 0;
- memset(minv,127,(m+1)*sizeof(int));
- memset(used,0,(m+1)*sizeof(int));
- do {
- used[j0] = true;
- li i0 = p[j0], delta = INF, j1 = 0;
- FORU(j,1,m) if(!used[j]) {
- li cur = ha[i0][j] - u[i0] - v[j];
- if(cur < minv[j]) { minv[j] = cur; way[j] = j0; }
- if(minv[j] < delta) { delta = minv[j]; j1 = j; }
- }
- FORU(j,0,m) {
- if(used[j]) { u[p[j]] += delta; v[j] -= delta; }
- else { minv[j] -= delta; }
- }
- j0 = j1;
- } while(p[j0] != 0);
- do {
- li j1 = way[j0];
- p[j0] = p[j1];
- j0 = j1;
- } while(j0);
- }
- return vi(p, p+m+1);
- }
- location locs[MAXN];
- int locsDists[MAXN][MAXN];
- void read_input(){
- cin >> n;
- n -= 1;
- cin>>sx>>sy;
- { int d; cin>>d>>d>>d>>d; }
- FOR(i,n) locs[i].read();
- FOR(i,n) {
- FOR(j,n) locsDists[i][j] = locs[i].dist(locs[j]);
- pdqsort(locsDists[i], locsDists[i]+n);
- }
- }
- const ld PHASE1_TIME = 10.0;
- const ld PHASE2_TIME = 12.0;
- const ld MAX_TIME = 14.5;
- const ld MIN_DIST = 1.0/100.0;
- const ld MAX_DIST = 1.0/5.0;
- int inflow[MAXN], outflow[MAXN];
- int intime[MAXN], outtime[MAXN];
- array<int, 7> weight[MAXN];
- int N[MAXN];
- int nc;
- int C[MAXN], IC[MAXN];
- int nq;
- int Q[MAXN];
- int flow_A[MAXN], flow_B[MAXN];
- int flow_nes;
- tuple<int,int,int> flow_ES[MAXN*MAXN];
- MaxFlow F;
- ld flowTime = 0;
- ld fullFlowTime = 0;
- ld initTime = 0;
- ld fullInitTime = 0;
- ld hungarianTime = 0;
- ld fullHungarianTime = 0;
- ld sortTime = 0;
- ld removeTime = 0;
- ld calcTime = 0;
- int ngraph[MAXN], nrgraph[MAXN];
- array<int,7> graph[MAXN], rgraph[MAXN];
- void solve() {
- li goal = 0;
- FOR(i,n) goal += locs[i].p;
- li cur = 0;
- int niter = 0;
- // Initialization
- auto init = [&](int maxDist) {
- ld t0 = getTime();
- nc = 0;
- memset(N, 0, n * sizeof(int));
- FOR(i,n) FOR(j0,ngraph[i]) N[graph[i][j0]]++;
- nq = 0;
- FOR(i,n) if(!N[i]) Q[nq++] = i;
- while(nq) {
- swap(Q[random(nq)], Q[nq-1]);
- int i = Q[--nq];
- C[nc++] = i;
- FOR(j0,ngraph[i]) {
- int j = graph[i][j0];
- N[j]--;
- if(!N[j]) Q[nq++] = j;
- }
- }
- FOR(i0, n) {
- int i = C[i0];
- intime[i] = locs[i].from + locs[i].duration;
- FOR(j0, nrgraph[i]) intime[i] = max(intime[i], intime[rgraph[i][j0]] + locs[i].dist(locs[rgraph[i][j0]]) + locs[i].duration);
- }
- FORD(i0,n-1,0) {
- int i = C[i0];
- outtime[i] = locs[i].to;
- FOR(j0, ngraph[i]) outtime[i] = min(outtime[i], outtime[graph[i][j0]] - locs[i].dist(locs[graph[i][j0]]) - locs[i].duration);
- }
- vi time(n);
- if(random(2)) {
- FOR(i,n) time[i] = intime[i] - locs[i].duration;
- }else{
- FOR(i,n) time[i] = outtime[i];
- }
- F.reset();
- int S = F.addNode(), T = F.addNode();
- FOR(i,n) {
- flow_A[i] = F.addNode();
- F.addEdge(S, flow_A[i], locs[i].p);
- }
- FOR(i,n) {
- flow_B[i] = F.addNode();
- F.addEdge(flow_B[i], T, locs[i].p);
- }
- flow_nes = 0;
- FOR(i,n) FOR(j,n) if(i!=j && time[i] + locs[i].duration + locs[i].dist(locs[j]) <= time[j] && locs[i].dist(locs[j]) <= locsDists[i][maxDist]) {
- flow_ES[flow_nes++] = mt(i,j,F.addEdge(flow_A[i], flow_B[j], min(locs[i].p, locs[j].p)));
- }
- ld t1 = getTime();
- F.flow(S, T);
- initTime += getTime() - t1;
- cur = 0;
- FOR(i,n) {
- ngraph[i] = 0;
- nrgraph[i] = 0;
- inflow[i] = 0;
- outflow[i] = 0;
- }
- FOR(k, flow_nes) {
- int i,j,ix; tie(i,j,ix) = flow_ES[k];
- int f = F.G[flow_A[i]][ix].flow;
- if(f) {
- cur += f;
- weight[i][ngraph[i]] = f;
- graph[i][ngraph[i]++] = j;
- rgraph[j][nrgraph[j]++] = i;
- outflow[i] += f;
- inflow[j] += f;
- }
- }
- fullInitTime += getTime() - t0;
- };
- init(n*MIN_DIST);
- while(1) {
- niter++;
- double t = getTime();
- int phase = 1;
- ld done = (ld)t/(ld)PHASE1_TIME;
- if(t > PHASE1_TIME) {
- done = (ld)(t-PHASE1_TIME)/(ld)(PHASE2_TIME-PHASE1_TIME);
- phase = 2;
- }
- if(t > PHASE2_TIME) {
- done = (ld)(t-PHASE2_TIME)/(ld)(MAX_TIME-PHASE2_TIME);
- phase = 3;
- }
- if(t > MAX_TIME) break;
- int maxDist = min<int>(phase == 1 ? (n * MIN_DIST) + pow(done, 1.5) * (n*MAX_DIST-n*MIN_DIST) : n*MAX_DIST, n-1);
- if(phase <= 2 && niter % 1200 == 1199) {
- init(maxDist);
- continue;
- }
- ld t2 = getTime();
- // compute a random topological sort
- nc = 0;
- int ty = random(2);
- if(ty == 0) {
- memset(N, 0, n * sizeof(int));
- FOR(i,n) FOR(j0, ngraph[i]) N[graph[i][j0]]++;
- nq = 0;
- FOR(i,n) if(!N[i]) Q[nq++] = i;
- while(nq) {
- swap(Q[random(nq)], Q[nq-1]);
- int i = Q[--nq];
- IC[i] = nc;
- C[nc++] = i;
- FOR(j0, ngraph[i]) {
- int j = graph[i][j0];
- N[j]--;
- if(!N[j]) Q[nq++] = j;
- }
- }
- }else if(ty == 1){
- memset(N, 0, n * sizeof(int));
- FOR(i,n) FOR(j0, nrgraph[i]) N[rgraph[i][j0]]++;
- nq = 0;
- FOR(i,n) if(!N[i]) Q[nq++] = i;
- while(nq) {
- swap(Q[random(nq)], Q[nq-1]);
- int i = Q[--nq];
- IC[i] = n-1-nc;
- C[n-1-(nc++)] = i;
- FOR(j0, nrgraph[i]) {
- int j = rgraph[i][j0];
- N[j]--;
- if(!N[j]) Q[nq++] = j;
- }
- }
- }
- sortTime += getTime() - t2;
- ld t4 = getTime();
- // compute min/max times
- FOR(i0,n) {
- int i = C[i0];
- intime[i] = locs[i].from + locs[i].duration;
- FOR(j0, nrgraph[i]) intime[i] = max(intime[i], intime[rgraph[i][j0]] + locs[i].dist(locs[rgraph[i][j0]]) + locs[i].duration);
- }
- FORD(i0,n-1,0) {
- int i = C[i0];
- outtime[i] = locs[i].to;
- FOR(j0, ngraph[i]) outtime[i] = min(outtime[i], outtime[graph[i][j0]] - locs[i].dist(locs[graph[i][j0]]) - locs[i].duration);
- }
- calcTime += getTime() - t4;
- if(phase <= 2 || (phase == 3 && done < 0.5)) {
- { int i = random(n);
- if(ngraph[i] != 1) goto l_NoImp;
- int j0 = random(ngraph[i]);
- int j = graph[i][j0];
- if(nrgraph[j] != 1) goto l_NoImp;
- if(inflow[i] > locs[j].p) goto l_NoImp;
- if(outflow[j] > locs[i].p) goto l_NoImp;
- if(locs[j].dist(locs[i]) > locsDists[j][maxDist]) goto l_NoImp;
- int tj = locs[j].from + locs[j].duration;
- li mx0 = 0, mx1 = 0;
- li mxg0 = 0, mxg1 = 0;
- FOR(k0, nrgraph[i]) {
- mx0 = max(mx0, locs[i].dist(locs[rgraph[i][k0]]));
- mx1 = max(mx1, locs[j].dist(locs[rgraph[i][k0]]));
- if(locs[rgraph[i][k0]].dist(locs[j]) > locsDists[rgraph[i][k0]][maxDist]) goto l_NoImp;
- tj = max(tj, intime[rgraph[i][k0]] + locs[j].dist(locs[rgraph[i][k0]]) + locs[j].duration);
- }
- if(tj > locs[j].to) goto l_NoImp;
- int ti = max(locs[i].from + locs[i].duration, tj + locs[i].dist(locs[j]) + locs[i].duration);
- if(ti > locs[i].to) goto l_NoImp;
- FOR(k0, ngraph[j]) {
- mxg0 = max(mxg0, locs[j].dist(locs[graph[j][k0]]));
- mxg1 = max(mxg1, locs[i].dist(locs[graph[j][k0]]));
- if(locs[graph[j][k0]].dist(locs[i]) > locsDists[i][maxDist]) goto l_NoImp;
- if(ti + locs[i].dist(locs[graph[j][k0]]) > outtime[graph[j][k0]]) goto l_NoImp;
- }
- if(max(mx0,mxg0) < max(mx1,mxg1)) goto l_NoImp;
- // cout << "OK " << i << ":" << nrgraph[i] << " " << ngraph[i] << " " << j << ":" << nrgraph[j] << " " << ngraph[j] << endl;
- swap(nrgraph[i], nrgraph[j]);
- swap(rgraph[i], rgraph[j]);
- swap(ngraph[i], ngraph[j]);
- swap(graph[i], graph[j]);
- swap(inflow[i], inflow[j]);
- swap(outflow[i], outflow[j]);
- swap(weight[i], weight[j]);
- // weight[j][i] = weight[i][j];
- // weight[i][j] = 0;
- rgraph[i][0] = j;
- graph[j][0] = i;
- FOR(k0, ngraph[i]) {
- int k = graph[i][k0];
- *find(begin(rgraph[k]), begin(rgraph[k]) + nrgraph[k], j) = i;
- }
- FOR(k0, nrgraph[j]) {
- int k = rgraph[j][k0];
- *find(begin(graph[k]), begin(graph[k]) + ngraph[k], i) = j;
- }
- continue;
- }
- l_NoImp:;
- }
- ld t3 = getTime();
- // remove edges between the two parts
- int th = random(n+1);
- FOR(i,n) if(IC[i]<th) {
- FOR(j0, ngraph[i]) while(j0 < ngraph[i] && IC[graph[i][j0]] >= th) {
- int j = graph[i][j0];
- cur -= weight[i][j0];
- outflow[i] -= weight[i][j0];
- inflow[j] -= weight[i][j0];
- swap(graph[i][j0], graph[i][ngraph[i]-1]);
- swap(weight[i][j0], weight[i][ngraph[i]-1]);
- ngraph[i]--;
- }
- }
- FOR(i,n) if(IC[i]>=th) {
- FOR(j0, nrgraph[i]) while(j0 < nrgraph[i] && IC[rgraph[i][j0]] < th) {
- swap(rgraph[i][j0], rgraph[i][nrgraph[i]-1]);
- nrgraph[i]--;
- }
- }
- removeTime += getTime() - t3;
- if(phase >= 2) {
- ld t0 = getTime();
- vi as, bs;
- FOR(i0,th) FOR(k, locs[C[i0]].p - outflow[C[i0]]) as.pb(C[i0]);
- FORU(i0,th,n-1) FOR(k, locs[C[i0]].p - inflow[C[i0]]) bs.pb(C[i0]);
- int na = as.size(), nb = bs.size();
- if(na <= nb) {
- FOR(i0,na) FOR(j0,nb) {
- int i = as[i0], j = bs[j0];
- if(locs[i].dist(locs[j]) <= locsDists[i][maxDist] && intime[i] + locs[i].dist(locs[j]) <= outtime[j]) {
- ha[i0+1][j0+1] = (phase == 2 ? 4.0 * (1 - done) * locs[i].dist(locs[j]) : 0) +
- ((1000 - intime[i]) + + outtime[j]) +
- ((400 - locs[i].sdist) + (-locs[j].sdist));
- } else {
- ha[i0+1][j0+1] = 1e6;
- }
- }
- ld t1 = getTime();
- vi p = hungarian(na, nb);
- hungarianTime += getTime() - t1;
- FORU(j0,1,nb) if(p[j0]) {
- int i = as[p[j0]-1];
- int j = bs[j0-1];
- if(intime[i] + locs[i].dist(locs[j]) <= outtime[j]) {
- int j0 = 0;
- while(j0 < ngraph[i] && graph[i][j0] != j) j0++;
- if(j0 == ngraph[i]) {
- weight[i][ngraph[i]] = 0;
- graph[i][ngraph[i]++] = j;
- rgraph[j][nrgraph[j]++] = i;
- }
- weight[i][j0] += 1;
- outflow[i] += 1;
- inflow[j] += 1;
- cur += 1;
- }
- }
- }else{
- FOR(i0,na) FOR(j0,nb) {
- int i = as[i0], j = bs[j0];
- if(locs[i].dist(locs[j]) <= locsDists[i][maxDist] && intime[i] + locs[i].dist(locs[j]) <= outtime[j]) {
- ha[j0+1][i0+1] = (phase == 2 ? 4.0 * (1 - done) * locs[i].dist(locs[j]) : 0) +
- ((1000 - intime[i]) + + outtime[j]) +
- ((400 - locs[i].sdist) + (-locs[j].sdist));
- } else {
- ha[j0+1][i0+1] = 1e6;
- }
- }
- ld t0 = getTime();
- vi p = hungarian(nb, na);
- hungarianTime += getTime() - t0;
- FORU(i0,1,na) if(p[i0]) {
- int i = as[i0-1];
- int j = bs[p[i0]-1];
- if(intime[i] + locs[i].dist(locs[j]) <= outtime[j]) {
- int j0 = 0;
- while(j0 < ngraph[i] && graph[i][j0] != j) j0++;
- if(j0 == ngraph[i]) {
- weight[i][ngraph[i]] = 0;
- graph[i][ngraph[i]++] = j;
- rgraph[j][nrgraph[j]++] = i;
- }
- weight[i][j0] += 1;
- outflow[i] += 1;
- inflow[j] += 1;
- cur += 1;
- }
- }
- }
- fullHungarianTime += getTime() - t0;
- }else{
- ld t0 = getTime();
- vi as, bs;
- FOR(i0,th) if(outflow[C[i0]] < locs[C[i0]].p) as.pb(C[i0]);
- FORU(i0,th,n-1) if(inflow[C[i0]] < locs[C[i0]].p) bs.pb(C[i0]);
- F.reset();
- int S = F.addNode(), T = F.addNode();
- for(int i : as) {
- flow_A[i] = F.addNode();
- F.addEdge(S, flow_A[i], locs[i].p - outflow[i]);
- }
- for(int i : bs) {
- flow_A[i] = F.addNode();
- F.addEdge(flow_A[i], T, locs[i].p - inflow[i]);
- }
- flow_nes = 0;
- for(int i : as) for(int j : bs) if(locs[i].dist(locs[j]) <= locsDists[i][maxDist] && intime[i] + locs[i].dist(locs[j]) <= outtime[j]) {
- flow_ES[flow_nes++] = mt(i,j,F.addEdge(flow_A[i], flow_A[j], min(locs[i].p, locs[j].p)));
- }
- ld t1 = getTime();
- int f = F.flow(S, T);
- flowTime += getTime() - t1;
- (void)f;
- // add the new edges
- FOR(k, flow_nes) {
- int i,j,ix; tie(i,j,ix) = flow_ES[k];
- li f = F.G[flow_A[i]][ix].flow;
- if(f) {
- weight[i][ngraph[i]] = f;
- cur += f;
- graph[i][ngraph[i]++] = j;
- rgraph[j][nrgraph[j]++] = i;
- outflow[i] += f;
- inflow[j] += f;
- }
- }
- fullFlowTime += getTime() - t0;
- }
- if(niter % 100 == 0) {
- cerr << "niter = " << niter << ", cur = " << goal-cur << ", done = " << done << endl;
- }
- }
- // Initialize the LPSolver with a feasible solution
- vi O;
- { vi N(n, 0);
- FOR(i,n) FOR(j0, ngraph[i]) N[graph[i][j0]]++;
- vi Q;
- FOR(i,n) if(!N[i]) Q.pb(i);
- while(!Q.empty()) {
- swap(Q[random(Q.size())], Q.back());
- int i = Q.back(); Q.pop_back();
- O.pb(i);
- FOR(j0, ngraph[i]) {
- int j = graph[i][j0];
- N[j]--;
- if(!N[j]) Q.pb(j);
- }
- }
- for(int i : O) {
- intime[i] = locs[i].from;
- FOR(j0, nrgraph[i]) intime[i] = max(intime[i], intime[rgraph[i][j0]] + locs[i].dist(locs[rgraph[i][j0]]) + locs[rgraph[i][j0]].duration);
- }
- }
- // Run the LPSolver
- { vvd A;
- vd B;
- vd C(n);
- FOR(i,n) C[i] = outflow[i] - inflow[i];
- FOR(i,n) {
- A.eb(n, 0);
- A.back()[i] = 1;
- B.eb(locs[i].to - intime[i]);
- }
- FOR(i,n) {
- set<int> seen;
- FOR(j0, ngraph[i]) {
- int j = graph[i][j0];
- if(seen.count(j)) continue;
- seen.insert(j);
- A.eb(n, 0);
- A.back()[i] = 1;
- A.back()[j] = -1;
- B.eb(intime[j] - intime[i] - locs[i].duration - locs[i].dist(locs[j]));
- }
- }
- LPSolver S(A,B,C);
- vd x;
- ld co = S.Solve(x);
- (void)co;
- FOR(i,n) intime[i] = intime[i]+x[i];
- }
- li cost = 0;
- FOR(i,n) cost += (2 * locs[i].p - inflow[i] - outflow[i]) * locs[i].sdist;
- FOR(i,n) cost += intime[i] * inflow[i] - (intime[i] + locs[i].duration) * outflow[i] + locs[i].p * locs[i].duration;
- li baseSc = 0;
- FOR(i,n) if(locs[i].p) baseSc += locs[i].score;
- cerr << "baseSc = " << baseSc << endl;
- cerr << "nw cost = " << (goal-cur) * 240 << endl;
- cerr << "route cost = " << cost << endl;
- cerr << "total = " << baseSc - (goal-cur) * 240 - cost << endl;
- cerr << "flow time = " << flowTime << endl;
- cerr << "full flow time = " << fullFlowTime << endl;
- cerr << "init time = " << initTime << endl;
- cerr << "full init time = " << fullInitTime << endl;
- cerr << "hungarian time = " << hungarianTime << endl;
- cerr << "full hungarian time = " << fullHungarianTime << endl;
- cerr << "sort time = " << sortTime << endl;
- cerr << "remove time = " << removeTime << endl;
- cerr << "calc time = " << calcTime << endl;
- #ifdef CP_GEN
- { vvi routes;
- vvi routesAt(n);
- for(int i : O) {
- FOR(j0, nrgraph[i]) {
- int i0 = 0; while(graph[rgraph[i][j0]][i0] != i) i0++;
- FOR(k, weight[rgraph[i][j0]][i0]) {
- int r = routesAt[rgraph[i][j0]].back();
- routesAt[rgraph[i][j0]].pop_back();
- routes[r].pb(i);
- routesAt[i].pb(r);
- }
- }
- FOR(k, locs[i].p - inflow[i]) {
- int r = routes.size();
- routes.eb();
- routes[r].pb(i);
- routesAt[i].pb(r);
- }
- }
- for(auto const& R : routes) {
- cout << "start " << intime[R[0]] - locs[R[0]].sdist << " 1\n";
- for(int i : R) {
- cout << "arrive " << intime[i] << " " << 2+i << '\n';
- cout << "work " << intime[i] << " " << intime[i]+locs[i].duration << " " << 2+i << '\n';
- }
- cout << "arrive " << intime[R.back()]+locs[R.back()].duration+locs[R.back()].sdist << " 1\n";
- cout << "end\n";
- }
- cout << flush;
- }
- #endif
- }
- int main() {
- random_reset();
- read_input();
- cerr << "n = " << n << endl;
- solve();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement