POJ-3164-Command Network(最小树形图)

最小树形图

http://blog.csdn.net/wsniyufang/article/details/6747392

题意:给出一个有向图,求以root为根的最小树形图

// File Name: 3164.cpp
// Author: zlbing
// Created Time: 2013/2/17 18:46:24

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define MAXN 105
#define INF 0x3f3f3f3f
#define CL(x,v); memset(x,v,sizeof(x));

struct point{
    int x,y;
}p[MAXN];
double dis(point a,point b)
{
    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
struct Edge{
    int from,to;
    double dist;
}edges[MAXN*MAXN];
double In[MAXN];
int pre[MAXN],ID[MAXN],vis[MAXN];
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=edges[i].from;
            int v=edges[i].to;
            if(edges[i].dist<In[v]&&u!=v)
            {
                pre[v]=u;
                In[v]=edges[i].dist;
            }
        }
        //2、判断是否有最小生成树
        for(int i=0;i<n;i++)
        {
            if(i==root)continue;
            if(In[i]==INF)return -1;
        }
        //3、找环
        int cntnode=0;
        CL(ID,-1);
        CL(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&&v!=root)
            {
                vis[v]=i;
                v=pre[v];
            }
            if(v!=root&&ID[v]==-1)
            {
                for(int u=pre[v];u!=v;u=pre[u])
                {
                    ID[u]=cntnode;
                }
                ID[v]=cntnode++;
            }
        }
        if(cntnode==0)break;
        for(int i=0;i<n;i++)
            if(ID[i]==-1)
                ID[i]=cntnode++;
        //4、缩点,重新标记
        for(int i=0;i<m;i++)
        {
            int v=edges[i].to;
            edges[i].from=ID[edges[i].from];
            edges[i].to=ID[edges[i].to];
            if(edges[i].from!=edges[i].to)
            {
                edges[i].dist-=In[v];
            }
        }
        n=cntnode;
        root=ID[root];
    }
    return ans;
}
int main(){
    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);
        int a,b;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            a--,b--;
            edges[i].from=a;
            edges[i].to=b;
            if(a!=b)
            edges[i].dist=dis(p[a],p[b]);
            else edges[i].dist=INF;
        }
        double ans=Directed_MST(0,n,m);
        if(ans==-1)
            printf("poor snoopy\n");
        else printf("%.2lf\n",ans);
    }
    return 0;
}

 

posted @ 2013-02-17 22:32  z.arbitrary  阅读(185)  评论(0编辑  收藏  举报