HDU 4009 Transfer water (minimum tree diagram + virtual root)

Question: There is a village that needs to build a water supply system. Each household’s house has a three-dimensional coordinate, and each household can choose to dig a well or draw water from other residents’ houses. Digging a well and diverting water require different amounts of money. Each household has a wish list, and they are only willing to supply water to the residents in the list. Finally, it is required to calculate the minimum cost of water supply for all residents.

Problem solution: minimum tree diagram + virtual root
Create a virtual root, connect the virtual root to all points, and the edge weight is the cost of digging a well for that point.

Others built sides according to the wishes of the residents and ran Zhu Liu.

The array is too small to time out.

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1010;
const int MAXM = 1000010;
struct Edge {
    
    
	int u, v;
	int cost;
}edge[MAXM];
int pre[MAXN], id[MAXN], vis[MAXN];
int in[MAXN];
int zhuliu(int rt, int n, int m) {
    
    
	int u, v;
	int res = 0;
	while (1) {
    
    
		for (int i = 0; i < n; i++) in[i] = INF;
		for (int i = 0; i < m; i++)
			if (edge[i].u != edge[i].v && edge[i].cost < in[edge[i].v]) {
    
    
				pre[edge[i].v] = edge[i].u;
				in[edge[i].v] = edge[i].cost;
				//if (edge[i].u == rt) pos = i;   //虚根
			}
		for (int i = 0; i < n; i++)
			if (i != rt && in[i] == INF) return -1;//不存在最小树形图
		int tn = 0;
		memset(id, -1, sizeof(id));
		memset(vis, -1, sizeof(vis));
		in[rt] = 0;
		for (int i = 0; i < n; i++) {
    
    
			res += in[i];
			v = i;
			while (vis[v] != i && id[v] == -1 && v != rt) {
    
    
				vis[v] = i;
				v = pre[v];
			}
			if (v != rt && id[v] == -1) {
    
    
				for (int u = pre[v]; u != v; u = pre[u]) id[u] = tn;
				id[v] = tn++;
			}
		}
		if (tn == 0) break;//没有有向环
		for (int i = 0; i < n; i++)
			if (id[i] == -1) id[i] = tn++;
		for (int i = 0; i < m; i++) {
    
    
			v = edge[i].v;
			edge[i].u = id[edge[i].u];
			edge[i].v = id[edge[i].v];
			if (edge[i].u != edge[i].v) edge[i].cost -= in[v];
		}
		n = tn;
		rt = id[rt];
	}
	return res;
}
int n, x, y, z, a[MAXN], b[MAXN], c[MAXN];
int dis(int xa, int ya, int za, int xb, int yb, int zb) {
    
    
	return (abs(xa - xb) + abs(ya - yb) + abs(za - zb)) * y + (za >= zb ? 0 : z);
}
int main() {
    
    
	while (~scanf("%d%d%d%d", &n, &x, &y, &z) && n) {
    
    
		for (int i = 0; i < n; i++) scanf("%d%d%d", &a[i], &b[i], &c[i]);
		int L = 0;
		for (int i = 0; i < n; i++) {
    
    
			int k, temp;
			scanf("%d", &k);
			for (int j = 1; j <= k; j++) {
    
    
				scanf("%d", &temp); temp--;
				if (i == temp) continue;
				edge[L].u = i;
				edge[L].v = temp;
				edge[L++].cost = dis(a[i], b[i], c[i], a[temp], b[temp], c[temp]);
			}
		}
		for (int i = 0; i < n; i++) {
    
    
			edge[L].u = n;
			edge[L].v = i;
			edge[L++].cost = x * c[i];
		}
		printf("%d\n", zhuliu(n, n + 1, L));
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_43680965/article/details/107826584