POJ 3164 Command Network (最小树形图)

题意:求有向图的最小生成树。

题解:最小树形图
模板题。

注意几点:
①double
②自环重边

#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 = 40010;
struct Edge {
    
    
	int u, v;
	double cost;
}edge[MAXM];
int pre[MAXN], id[MAXN], vis[MAXN];
double in[MAXN];
double zhuliu(int rt, int n, int m) {
    
    
	int u, v;
	double 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;
			}
		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;) {
    
    
			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];
			else swap(edge[i], edge[--m]);
		}
		n = tn;
		rt = id[rt];
	}
	return res;
}
int n, m;
double g[MAXN][MAXN], x[MAXN], y[MAXN];
double dis(double xa, double ya, double xb, double yb) {
    
    
	return sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
}
int main() {
    
    
	while (~scanf("%d%d", &n, &m)) {
    
    
		for (int i = 0; i < n; i++) {
    
    
			for (int j = 0; j < n; j++) {
    
    
				g[i][j] = INF;
			}
		}
		for (int i = 0; i < n; i++) scanf("%lf%lf", &x[i], &y[i]);
		int u, v;
		while (m--) {
    
    
			scanf("%d%d", &u, &v); u--, v--;
			if (u == v)continue;
			//cout << g[u][v] << endl;
			g[u][v] = min(g[u][v], dis(x[u], y[u], x[v], y[v]));
			
		}
		int L = 0;
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				if (g[i][j] < INF) {
    
    
					edge[L].u = i;
					edge[L].v = j;
					edge[L++].cost = g[i][j];
					//cout << 1;
				}
		double ans = zhuliu(0, n, L);
		if (ans == -1) puts("poor snoopy");
		else printf("%.2f\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43680965/article/details/107801844