码迷,mamicode.com
首页 > Web开发 > 详细

【POJ3164】Command Network 最小树形图模板题 重修版

时间:2015-04-08 09:07:57      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:poj3164   最小树形图   模板题   重修版   

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44935891");
}

我以前的版本

算法构造过程以及傻叉代码+弱版注释见以前博客
http://blog.csdn.net/vmurder/article/details/38819711

最小树形图:

名词解释:

       其实就是有向图的最小生成树,然后需要有一个根(一般默认为1),如果是无根最小树形图,我们可以牺牲时间复杂度, O(n) 枚举根跑最小树形图。

算法流程:

  1. 对于一张有向图,除了根以外每个点都找一条权值最小的入边(称之为 [最小弧] )
  2. 这样就可能构成了一片由基环树组成的森林,然后我们把每个环都缩点,并根据点的新编号重建图。但是如果没有环(所有点与根连通),则最小树形图已经建成,跳出流程。

如果计算边权:

每次将所有点(根除外)最小弧长度累加,重建图时与x相连的边权值全部减去此最小弧长度,这样就保证了最后一个点的流程中加得的所有最小弧长度等于最后一次加的边的原长度。

代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define inf 0x3f3f3f3f
#define N 200
#define M 50000
using namespace std;
struct Fiona
{
    double x,y;
}s[N];
struct Syndra
{
    int u,v;
    double w;
}e[M];
int pre[N],f[N],vis[N];
double l[N];
double dist(Fiona A,Fiona B)
{
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
double Directed_MST(int root,int n,int m)
{
    int i,j,k;
    int u,v,cnt;
    double ans=0;
    while(1)
    {
        for(i=1;i<=n;i++)f[i]=vis[i]=0,l[i]=inf;
        for(i=1;i<=m;i++)
        {
            u=e[i].u;v=e[i].v;
            if(l[v]>e[i].w)pre[v]=u,l[v]=e[i].w;
        }
        for(i=1;i<=n;i++)if(l[i]==inf&&i!=root)return -1;
        l[root]=cnt=0;
        for(i=1;i<=n;i++)
        {
            ans+=l[i];
            if(vis[i])continue;
            for(v=i;!vis[v]&&v!=root;vis[v]=i,v=pre[v]);
            if(v!=root&&vis[v]==i)
            {
                f[v]=++cnt;
                for(u=pre[v];u!=v;u=pre[u])f[u]=cnt;
            }
        }
        if(!cnt)break;
        for(i=1;i<=n;i++)if(!f[i])f[i]=++cnt;
            n=cnt,cnt=0,root=f[root];
        for(i=1;i<=m;i++)
        {
            u=e[i].u,v=e[i].v;
            if(f[u]!=f[v])
            {
                e[++cnt].u=f[u];
                e[cnt].v=f[v];
                e[cnt].w=e[i].w-l[v];
            }
        }
        m=cnt;
    }
    return ans;
}
int main()
{
    freopen("test.in","r",stdin);
    int i,n,m;
    double ans;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=1;i<=n;i++)scanf("%lf%lf",&s[i].x,&s[i].y);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&e[i].u,&e[i].v);
            if(e[i].u!=e[i].v)e[i].w=dist(s[e[i].u],s[e[i].v]);
            else i--,m--;
        }
        ans=Directed_MST(1,n,m);
        if(ans==-1)printf("poor snoopy\n");
        else printf("%.2f\n",ans);
    }
    return 0;
}

【POJ3164】Command Network 最小树形图模板题 重修版

标签:poj3164   最小树形图   模板题   重修版   

原文地址:http://blog.csdn.net/vmurder/article/details/44935891

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!