Command Network

来源:互联网 发布:it之家官网 编辑:程序博客网 时间:2024/05/18 19:42

题目:

  http://poj.org/problem?id=3164

题意:

  裸最小树形图,套模板就可以。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>using namespace std;#define maxn 107#define memset(a,b) memset(a,b,sizeof(a))const int INF = 0x3f3f3f3f;int pre[maxn],id[maxn],vis[maxn];double in[maxn];struct {    int x,y;}p[maxn];struct {    int u,v;    double w;}edge[maxn*maxn];double dis(int a, int b) {    double x = p[a].x - p[b].x, y = p[a].y - p[b].y;    return sqrt(x*x+y*y);}double directed_MST(int root, int n, int m) {    double ans = 0;    while(true) {        //1.找最小入边        for (int i = 0; i < n; i++) in[i] = INF;        for (int i = 0; i < m; i++) {            int u = edge[i].u, v = edge[i].v;            if (edge[i].w < in[v] && u != v) {                pre[v] = u;                in[v] = edge[i].w;            }        }        for (int i =0; i < n; i++)            if (in[i] == INF && i != root)                return -1;        //2.找环        int cnt = 0;        memset(id, -1);        memset(vis, -1);        in[root] = 0;        for (int i = 0; i < n; i++) {            ans += in[i];            int v = i;            while (vis[v] != i && id[v] == -1) {//缩点                vis[v] = i;                v = pre[v];            }            if (v != root && id[v] == -1) {                for (int u = pre[v]; u != v; u = pre[u]) id[u] = cnt;                id[v] = cnt++;            }        }        if(cnt == 0) break;        for(int i=0 ; i<n ; i++) if(id[i] == -1) id[i] = cnt++;        //3.建立新图        for(int i=0 ; i<m ; 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];        }        n = cnt;        root = id[root];    }    return ans;}int main() {#ifndef ONLINE_JUDGE    freopen("/home/lucienshui/Desktop/in","r",stdin);#endif    int n,m;    while(~scanf("%d%d",&n,&m)) {        for(int i=0 ; i<n ; i++) scanf("%d%d",&p[i].x,&p[i].y);        for(int i=0 ; i<m ; i++) {            scanf("%d%d",&edge[i].u,&edge[i].v);            if(--edge[i].u!=--edge[i].v) edge[i].w = dis(edge[i].u,edge[i].v);            else edge[i].w = INF;        }        double ans = directed_MST(0,n,m);        if(ans == -1) printf("poor snoopy\n");        else printf("%.2f\n",ans);    }    return 0;}
原创粉丝点击