2021牛客暑期多校训练营5
J Jewels
黄金水手在海底捞钻石,给的是一个三维的坐标,一颗钻石每秒向上飘vi米,求最小捞的时间。
网络流的spfa版最大流,超时
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<string>
#include<string.h>
#define ll long long
using namespace std;
const int N = 4020, M = (10 + 2e4)*13;
const int inf = 0x3f3f3f;
int ver[M], Next[M], head[M];
ll edge[M], cost[M], incf[N];
int pre[N], v[N];
int n, k, tot, s, t;
ll maxflow, d[N], ans;
void add(int x, int y, ll z, ll c)
{
ver[++tot] = y, edge[tot] = z, cost[tot] = c;
Next[tot] = head[x], head[x] = tot;
ver[++tot] = x, edge[tot] = 0, cost[tot] = -c;
Next[tot] = head[y], head[y] = tot;
}
bool spfa()
{
queue<int> q;
memset(d, 0x3f3f, sizeof(d));
memset(v, 0, sizeof(v));
q.push(s);
d[s] = 0;
v[s] = 1;
incf[s] = 1 << 30;
while (q.size())
{
int x = q.front();
v[x] = 0;
q.pop();
for (int i = head[x]; i; i = Next[i])
{
if (!edge[i])continue;
int y = ver[i];
if (d[y] > d[x] + cost[i])
{
d[y] = d[x] + cost[i];
incf[y] = min(incf[x], edge[i]);
pre[y] = i;
if (!v[y])
v[y] = 1, q.push(y);
}
}
}
return d[t] < 0x3f3f3f3f;
}
void update()
{
int x = t;
while (x != s)
{
int i = pre[x];
edge[i] -= incf[t];
edge[i ^ 1] += incf[t];
x = ver[i ^ 1];
}
maxflow += incf[t];
ans += d[t] * incf[t];
}
int a[2005];
int main()
{
tot = 1;
int n;
scanf("%d", &n);
s = 2 * n + 1;
t = 2 * n + 2;
int x,y;
ll z,v;
for(int i=1;i<=n;i++){
add(s,i,1,0);
add(i+n,t,1,0);
}
for (int i = 1; i <= n; i++){
scanf("%d %d %lld %lld",&x,&y,&z,&v);
for(int j=1;j<=n;j++){
add(j,i+n,1,x*x+y*y+(z+j*v-v)*(z+j*v-v));
}
}
while (spfa())
update();
cout << ans << endl;
}
网络流dij(超时)
果然dij跑二分图不占优势
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
#include<functional>
#include<fstream>
#define ll long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int maxn = 1e4;
const int INF = 0x7fffffff;
const int mod = 1e9 + 7;
const double eps = 1e-7;
inline int read_int() {
char c;
int ret = 0, sgn = 1;
do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
if (c == '-') sgn = -1; else ret = c - '0';
while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
return sgn * ret;
}
inline ll read_ll() {
char c;
ll ret = 0, sgn = 1;
do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
if (c == '-') sgn = -1; else ret = c - '0';
while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
return sgn * ret;
}
struct edge {
int to, capacity, cost, rev;
edge() {}
edge(int to, int _capacity, int _cost, int _rev) :to(to), capacity(_capacity), cost(_cost), rev(_rev) {}
};
struct Min_Cost_Max_Flow {
int V, H[maxn + 5], dis[maxn + 5], PreV[maxn + 5], PreE[maxn + 5];
vector<edge> G[maxn + 5];
//调用前初始化
void Init(int n) {
V = n;
for (int i = 0; i <= V; ++i)G[i].clear();
}
//加边
void Add_Edge(int from, int to, int cap, int cost) {
G[from].push_back(edge(to, cap, cost, G[to].size()));
G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
}
//flow是自己传进去的变量,就是最后的最大流,返回的是最小费用
int Min_cost_max_flow(int s, int t, int f, int& flow) {
int res = 0; fill(H, H + 1 + V, 0);
while (f) {
priority_queue <pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
fill(dis, dis + 1 + V, INF);
dis[s] = 0; q.push(pair<int, int>(0, s));
while (!q.empty()) {
pair<int, int> now = q.top(); q.pop();
int v = now.second;
if (dis[v] < now.first)continue;
for (int i = 0; i < G[v].size(); ++i) {
edge& e = G[v][i];
if (e.capacity > 0 && dis[e.to] > dis[v] + e.cost + H[v] - H[e.to]) {
dis[e.to] = dis[v] + e.cost + H[v] - H[e.to];
PreV[e.to] = v;
PreE[e.to] = i;
q.push(pair<int, int>(dis[e.to], e.to));
}
}
}
if (dis[t] == INF)break;
for (int i = 0; i <= V; ++i)H[i] += dis[i];
int d = f;
for (int v = t; v != s; v = PreV[v])d = min(d, G[PreV[v]][PreE[v]].capacity);
f -= d; flow += d; res += d*H[t];
for (int v = t; v != s; v = PreV[v]) {
edge& e = G[PreV[v]][PreE[v]];
e.capacity -= d;
G[v][e.rev].capacity += d;
}
}
return res;
}
/*int Max_cost_max_flow(int s, int t, int f, int& flow) {
int res = 0;
fill(H, H + 1 + V, 0);
while (f) {
priority_queue <pair<int, int> > q;
fill(dis, dis + 1 + V, -INF);
dis[s] = 0;
q.push(pair<int, int>(0, s));
while (!q.empty()) {
pair<int, int> now = q.top(); q.pop();
int v = now.second;
if (dis[v] > now.first)continue;
for (int i = 0; i < G[v].size(); ++i) {
edge& e = G[v][i];
if (e.capacity > 0 && dis[e.to] < dis[v] + e.cost + H[v] - H[e.to]) {
dis[e.to] = dis[v] + e.cost + H[v] - H[e.to];
PreV[e.to] = v;
PreE[e.to] = i;
q.push(pair<int, int>(dis[e.to], e.to));
}
}
}
if (dis[t] == -INF)break;
for (int i = 0; i <= V; ++i)H[i] += dis[i];
int d = f;
for (int v = t; v != s; v = PreV[v])d = min(d, G[PreV[v]][PreE[v]].capacity);
f -= d; flow += d;
res += d*H[t];
for (int v = t; v != s; v = PreV[v]) {
edge& e = G[PreV[v]][PreE[v]];
e.capacity -= d;
G[v][e.rev].capacity += d;
}
}
return res;
}*/
};
Min_Cost_Max_Flow MCMF;
int n;
int main(){
scanf("%d",&n);
MCMF.Init(2*n+10);
int s=2*n+4,t=2*n+5;
//MCMF.Add_Edge(s,s2,k,0);
for(int i=1;i<=n;i++)
{
MCMF.Add_Edge(s,i,1,0);
MCMF.Add_Edge(i+n,t,1,0);
}
int x,y;
ll z,v;
for (int i = 1; i <= n; i++){
scanf("%d %d %lld %lld",&x,&y,&z,&v);
for(int j=1;j<=n;j++){
MCMF.Add_Edge(j,i+n,1,x*x+y*y+(z+j*v-v)*(z+j*v-v));
}
}
int flow0;
printf("%d\n",MCMF.Min_cost_max_flow(s,t,n,flow0));
return 0;
}
还差zkw费用流:先欠着
km板子(这个板子有点快):
#include <stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int N = 305;
struct node {
int s, z, v;
} a[N];
int n, match[N], last[N];
ll ans, w[N][N], la[N], lb[N], upd[N];
bool va[N], vb[N];
bool dfs(int x, int fa) {
va[x] = 1;
for (int y = 1; y <= n; y++)
if (!vb[y])
if (la[x] + lb[y] == w[x][y]) {
vb[y] = 1; last[y] = fa;
if (!match[y] || dfs(match[y], y)) {
match[y] = x;
return true;
}
}
else if (upd[y] > la[x] + lb[y] - w[x][y]) {
upd[y] = la[x] + lb[y] - w[x][y];
last[y] = fa;
}
return false;
}
void KM() {
for (int i = 1; i <= n; i++) {
la[i] = -(1ll << 62);
lb[i] = 0;
for (int j = 1; j <= n; j++)
la[i] = max(la[i], w[i][j]);
}
for (int i = 1; i <= n; i++) {
memset(va, 0, sizeof(va));
memset(vb, 0, sizeof(vb));
for (int j = 1; j <= n; j++) upd[j] = 1ll << 62;
int st = 0; match[st] = i;
while (match[st]) {
ll delta = 1ll << 62;
if (dfs(match[st], st)) break;
for (int j = 1; j <= n; j++)
if (!vb[j] && delta > upd[j]) {
delta = upd[j];
st = j;
}
for (int j = 1; j <= n; j++) {
if (va[j]) la[j] -= delta;
if (vb[j]) lb[j] += delta;
else upd[j] -= delta;
}
vb[st] = true;
}
while (st) {
match[st] = match[last[st]];
st = last[st];
}
}
}
ll x[5005], y[505], z[505],v[505];
unsigned main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld%lld%lld%lld", &x[i], &y[i], &z[i], &v[i]);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
w[i][j] = -1e18;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
w[i][j] = -(x[i] * x[i] + y[i] * y[i] + (z[i] + v[i] * (j - 1)) * (z[i] + v[i] * (j - 1)));
}
}
KM();
long long ans = 0;
for (int i = 1; i <= n; i++) {
if (match[i] != -1)ans -= w[match[i]][i];
}
printf("%lld\n", ans);
return 0;
}
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 410;
const int INF = 0x3f3f3f3f3f3f3f3f;
int b[N], c[N], s[N], w[N][N];
int lx[N], ly[N], linky[N], pre[N];
bool vis[N];
int slack[N];
int n;
struct Node{
int x, p;
bool operator < (const Node &W)const{
return x < W.x;
}
}a[N];
int cal(int x){
int l = 1, r = n;
while(l < r){
int mid = (l + r + 1) >> 1;
if(a[mid].x < x) l = mid;
else r = mid - 1;
}
if(a[l].x < x) return s[l];
else return 0;
}
void bfs(int k){
int px, py = 0, yy = 0;
int d;
memset(pre, 0, sizeof(pre));
memset(slack, 0x3f, sizeof(slack));
linky[py] = k;
do{
px = linky[py], d = INF, vis[py] = 1;
for(int i = 1; i <= n; i++){
if(!vis[i]){
if(slack[i] > lx[px] + ly[i] - w[px][i])
slack[i] = lx[px] + ly[i] - w[px][i], pre[i] = py;
if(slack[i] < d)
d = slack[i], yy = i;
}
}
for(int i = 0; i <= n; i++){
if(vis[i])
lx[linky[i]] -= d, ly[i] += d;
else
slack[i] -=d;
}
py = yy;
}while(linky[py]);
while(py){
linky[py] = linky[pre[py]], py = pre[py];
}
}
int km(){
memset(lx, 0, sizeof(lx));
memset(ly, 0, sizeof(ly));
memset(linky, 0, sizeof(linky));
for(int i = 1; i <= n; i++){
memset(vis, false, sizeof(vis));
bfs(i);
}
int ans = 0;
for(int i = 1; i <= n; i++)
ans += w[linky[i]][i];
return ans;
}
signed main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%lld", &a[i].x);
for(int i = 1; i <= n; i++)
scanf("%lld", &a[i].p);
for(int i = 1; i <= n; i++)
scanf("%lld", &b[i]);
for(int i = 1; i <= n; i++)
scanf("%lld", &c[i]);
sort(a + 1, a + 1 + n);
for(int i = 1; i <= n; i++)
s[i] = s[i - 1] + a[i].p;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
w[i][j] = cal(b[i] + c[j]);
}
}
printf("%lld\n", km());
return 0;
}