CF1107F Vasya and Endless Credits

lalaouye發表於2024-07-14

KM 做法這麼簡單好想為什麼都在 dp?我第一次過也是用的 dp。

建模非常好想,每天只能收一次錢,最簡單的思路是我們列舉第幾天開車跑路,但是再一想我們不關心是第幾天,只關心每次貸款離開車跑路還差幾天,於是我們從 \(i\)\(j\) 連邊,邊權是 \(a_i+b_i\times\min(k_i,j)\),意義為第 \(i\) 種貸款離買車還差 \(j\) 天對答案的貢獻,當然我們實現時需要對 \(0\) 取最大值,因為取 \(0\) 的意義為不參與答案貢獻,然而我們並不要求在最後一天開車,所以對 \(0\) 取最大值是必要的。

並且,容易證明我們不可能在某一天沒有進行任何操作。

所以建完模直接跑 KM 演算法即可,時間複雜度 \(\mathcal{O(n^3)}\)

程式碼:

#include <bits/stdc++.h>
#define int long long
#define rep(i, l, r) for (int i = l; i <= r; ++ i)
#define rrp(i, l, r) for (int i = r; i >= l; -- i)
#define eb emplace_back
#define inf 1000000000
#define linf 10000000000000000
#define pii pair <int, int>
using namespace std;
constexpr int N = 505, P = 1e9 + 7;
inline int rd ()
{
	int x = 0, f = 1;
	char ch = getchar ();
	while (! isdigit (ch)) { if (ch == '-') f = -1; ch = getchar (); }
	while (isdigit (ch)) { x = (x << 1) + (x << 3) + ch - 48; ch = getchar (); }
	return x * f;
}
int n, sum, ans;
int e[N][N];
int lx[N], ly[N], px[N], py[N], pre[N], slack[N];
bool vx[N], vy[N], flag;
int a[N], b[N], k[N];
queue <int> q;
void aug (int v)
{
  while (v)
  {
    int t = px[pre[v]];
    px[pre[v]] = v;
    py[v] = pre[v];
    v = t;
  }
}
void bfs (int s)
{
  memset (vx, 0, sizeof vx);
  memset (vy, 0, sizeof vy);
  memset (slack, 127, sizeof slack);
  while (! q.empty ()) q.pop ();
  q.push (s);
  while (true)
  {
    while (! q.empty ())
    {
      int u = q.front ();
      q.pop ();
      vx[u] = 1;
      rep (i, 1, n)
      {
        if (vy[i]) continue;
        if (lx[u] + ly[i] - e[u][i] < slack[i])
        {
          slack[i] = lx[u] + ly[i] - e[u][i];
          pre[i] = u;
          if(! slack[i])
          {
            vy[i] = 1;
            if (! py[i])
            {
              aug (i); return ;
            } else q.push (py[i]);
          }
        }  
      } 
    }
    int d = linf;
    rep (i, 1, n) if (! vy[i]) d = min (d, slack[i]);
    rep (i, 1, n)
    {
      if (vx[i]) lx[i] -= d, sum -= d;
      if (vy[i]) ly[i] += d, sum += d;
      else slack[i] -= d;
    }
    rep (i, 1, n)
    {
      if (vy[i]) continue;
      if(! slack[i])
      {
        vy[i] = 1;
        if (! py[i])
        {
          aug (i); return ;
        } else q.push (py[i]);
      }
    }
  }
}
void solve ()
{
  memset (lx, -127, sizeof lx);
  sum = 0;
  rep (i, 1, n) rep (j, 1, n) lx[i] = max (lx[i], e[i][j]);
  rep (i, 1, n) sum += lx[i];
  
  rep (i, 1, n)
    bfs (i);
}
signed main ()
{
  n = rd ();
  rep (i, 1, n)
  {
    a[i] = rd (), b[i] = rd (), k[i] = rd ();
  }
  rep (i, 1, n)
    rep (j, 1, n)
      e[i][j] = max (0ll, a[i] - min (k[i], j - 1) * b[i]);
  solve ();
  printf ("%lld\n", sum);
}
/*

*/