2021-08-02

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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值