社区讨论

一点小疑惑

P1500[集训队互测 2000] 丘比特的烦恼参与者 2已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@losdqhc7
此快照首次捕获于
2023/11/10 16:52
2 年前
此快照最后确认于
2023/11/10 19:28
2 年前
查看原帖
我建好了边,可是应该怎么改变Dinic才行啊。 Dinic:
CPP
//
// Created by lndff on  2023.11.09
//
#include <bits/stdc++.h>
using namespace std;

#define LL long long

const int N = 210000;
const int M = 501000;
const int INF = 0x3f3f3f3f;
template <typename T> inline void read(T &x){
	int w = 1;x = 0;char s;
	while (!isdigit(s = getchar())) if (s == '-') w = -1;
	while (isdigit(s)) x = (x << 3) + (x << 1), x += s - '0', s = getchar();
	x *= w;
}

int n, s, t, tot = 1, k, TOT;
int head[N], Next[M << 1], ver[M << 1], love[100][100], ANS;
LL d[N], w[M << 1], c[M << 1];
LL ans;
string name[100];
map<string, pair<int, int>>mp;
unordered_map<string, int> hax;
bool vis[N << 1];
void deals(string &s){
	for (auto i : s){
		if (i < 'a') i += 'a' - 'A';
	}
}

void add(int u, int v, LL ww, LL C){
	ver[++tot] = v;
	w[tot] = ww;
	Next[tot] = head[u];
	head[u] = tot;
	c[tot] = C;
	// cout << ww << " ";
}

inline int bfs(){
	for (register int i = 1; i <= n * 2 + 2; d[i] = INF, i++);
	queue<int> q;
	q.push(s);
	d[s] = 0;
	while (!q.empty()){
		int x = q.front();
		q.pop();
		for (int i = head[x]; i; i = Next[i]){
			if (w[i] > 0 && d[ver[i]] == INF){
				q.push(ver[i]);
				d[ver[i]] = d[x] + 1;
				if (ver[i] == t) return 1;
			}
		}
	}
	return 0;
}

inline int dfs(int x, LL sumflow){
	if (x == t) return sumflow;
	LL res, ret = 0;
	vis[x] = 1;
	for (int i =head[x]; i && sumflow; i = Next[i]){
		if (w[i] && (d[ver[i]] == d[x] + w[i]) && !vis[ver[i]]){
			res = dfs(ver[i], min(sumflow, w[i]));
			if (!res) d[ver[i]] = INF;
			w[i] -= res;
			w[i ^ 1] += res;
			ret += res;
			sumflow -= res;
			ANS += c[i] * res;
		}
	}
	return ret;
}
signed main(){
	read(k);
	read(n);
	int ww;
	for (int i = 1, x, y; i <= n; i++){
		cin >> x >> y >> name[i];
		deals(name[i]);
		mp[name[i]] = {x, y};
		hax[name[i]] = i;
	}
	for (int i = 1, x, y; i <= n; i++){
		cin >> x >> y >> name[i + n];
		deals(name[i + n]);
		mp[name[i + n]] = {x, y};
		hax[name[i + n]] = i + n;
	}
	string name1, name2;
	cin >> name1;
	while (name1 != "End"){
		cin >> name2;cin >> ww;
		deals(name1);deals(name2);
		int xx = mp[name1].first, xy = mp[name1].second, yx = mp[name2].first, yy = mp[name2].second;
		if ((xx - yx) * (xx - yx) + (xy - yy) * (xy - yy) <= k * k){
			int man = hax[name1], woman = hax[name2];
			if (man > woman) swap(man, woman);
			love[man][woman] = max(love[man][woman], ww);
		}
		cin >> name1;
	}
	for (int i = 1; i <= n; i++){
		for (int j = n + 1; j <= n * 2; j++){
			if (!love[i][j]){
				int xx = mp[name[i]].first, xy = mp[name[i]].second, yx = mp[name[j]].first, yy = mp[name[j]].second;
				if ((xx - yx) * (xx - yx) + (xy - yy) * (xy - yy) <= k * k){
					love[i][j] = 1;
				}
			}
		}
	}
	for (int i = 1; i <= n; i++){
		for (int j = n + 1; j <= n * 2; j++){
			// cout << "love[i][j]";
			int xx = mp[name[i]].first, xy = mp[name[i]].second, yx = mp[name[j]].first, yy = mp[name[j]].second;
			if ((xx - yx) * (xx - yx) + (xy - yy) * (xy - yy) <= k * k){
				add(i, j, 1, love[i][j]), add(j, i, 0, -love[i][j]);
			}
		}
	}
	s = n * 2 + 1;t = n * 2 + 2;
	for (int i = 1; i <= n; i++) add(s, i, 1, 0), add(i, s, 0, 0);
	for (int i = n + 1; i <= n * 2; i++) add(i, t, 1, 0), add(t, i, 0, 0);
	while (bfs()) {ans += dfs(s, INF);}
	return 0 * printf("%d", ANS);	
}
/*
2
3
0 0 Adam
1 1 Jack
0 2 George
1 0 Victoria
0 1 Susan
1 2 Cathy
Adam Cathy 100
Susan George 20
George Cathy 40
Jack Susan 5
Cathy Jack 30
Victoria Jack 20
Adam Victoria 15
End
*/
样例怎么测都只有60,似乎是因为边权变为一之后就没法反悔了。。。

回复

4 条回复,欢迎继续交流。

正在加载回复...