[POJ 3164][最小树形图]

来源:互联网 发布:自动化设备 图形 编程 编辑:程序博客网 时间:2024/05/18 09:09

朱刘算法

如果是不定根的话设置一个虚根,向所有点连sum(wi) + 1的边权,如果结果大于等于sum(wi) * 2 + 2说明无解

要输出%.2f

#define MAXN 110#include <algorithm>#include <cstring>#include <cstdio>#include <cmath>using namespace std;const double inf = 1e9;int n, m;struct Point { double x, y; } p[MAXN];double sqr(double x) { return x * x; }double dist(int i, int j) { return sqrt(sqr(p[i].x-p[j].x) + sqr(p[i].y-p[j].y)); }struct Edge { int u, v; double w; } edge[MAXN*MAXN];int id[MAXN], pre[MAXN], vis[MAXN];double in[MAXN];double Directed_MST(int root, int V, int E) {double ret = 0;while(true) {for(int i = 1 ; i <= V ; ++ i) in[i] = inf;for(int i = 1 ; i <= E ; ++ i) {int u = edge[i].u, v = edge[i].v;if(u != v && edge[i].w < in[v])in[v] = edge[i].w, pre[v] = u;  }in[root] = 0;for(int i = 1 ; i <= V ; ++ i)if(in[i] == inf) return -1;int cnt = 0;memset(id, 0, sizeof id);memset(vis, 0, sizeof vis);for(int i = 1 ; i <= V ; ++ i) {int v = i; ret += in[i];while(v != root && id[v] == 0 && vis[v] != i)vis[v] = i, v = pre[v];if(v != root && id[v] == 0) {id[v] = ++ cnt;for(int u = pre[v] ; u != v ; u = pre[u])id[u] = cnt;}}if(cnt == 0) return ret;for(int i = 1 ; i <= V ; ++ i)if(id[i] == 0) id[i] = ++ cnt;for(int i = 1 ; i <= E ; ++ i) {int u = edge[i].u, v = edge[i].v;edge[i].u = id[u], edge[i].v = id[v];if(id[u] != id[v]) edge[i].w -= in[v];}V = cnt, root = id[root];}}int main() {int u, v;while(~ scanf("%d%d", &n, &m)) {for(int i = 1 ; i <= n ; ++ i) scanf("%lf%lf", &p[i].x, &p[i].y);for(int i = 1 ; i <= m ; ++ i) {scanf("%d%d", &u, &v);if(u != v) edge[i] = (Edge){u, v, dist(u, v)};else edge[i] = (Edge){u, v, inf};}double ans = Directed_MST(1, n, m);if(ans == -1) printf("poor snoopy\n"); else printf("%.2f\n", ans);}return 0;}


0 0
原创粉丝点击