• POJ3164Command 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;
    }
  • 相关阅读:
    第十二章类的无参方法
    第十三章人机猜拳
    第十一章类和对象
    面向对象七大原则。
    深入类的方法。
    使用集合组织相关数据。
    .NET框架
    C#数据类型
    错误。
    实现Windows的数据绑定
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2915014.html
Copyright © 2020-2023  润新知