POJ-3164 Command Network 最小树形图

  题目链接:http://poj.org/problem?id=3164

  裸的最小树形图,用朱—刘算法解决,具体实现过程如下:算法一开始先判断从固定根开始是否可达所有原图中的点,若不可,则一定不存在最小树形图。这一步是一个很随便的搜索,写多搓都行,不加废话。第二步,遍历所有的边,从中找出除根结点外各点的最小入边,累加权值,构成新图。接着判断该图是否存在环。若不存在,则该图便是所求最小树型图,当前权为最小权。否则对环缩点,然后回到第二步继续判断。简化就是三个过程:找边—>找环—>缩点;

  算法流程图:

                        

 

  参考样例:

            

  代码实现有很多种方法,为了兼顾代码的长度和效率,我选择了O(VE)的写法。

  1 //STATUS:C++_AC_110MS_244KB
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<math.h>
  6 #include<iostream>
  7 #include<string>
  8 #include<algorithm>
  9 #include<vector>
 10 #include<queue>
 11 #include<stack>
 12 using namespace std;
 13 #define LL __int64
 14 #define pdi pair<double,int>
 15 #define Max(a,b) ((a)>(b)?(a):(b))
 16 #define Min(a,b) ((a)<(b)?(a):(b))
 17 #define mem(a,b) memset(a,b,sizeof(a))
 18 #define lson l,mid,rt<<1
 19 #define rson mid+1,r,rt<<1|1
 20 const int N=110,M=1000000,INF=0x3f3f3f3f,MOD=1999997;
 21 const LL LLNF=0x3f3f3f3f3f3f3f3fLL;
 22 const double DNF=100000000000;
 23 
 24 struct Node{
 25     double x,y;
 26 }nod[N];
 27 struct Edge{
 28     int u,v;
 29     double w;
 30 }e[N*N];
 31 int pre[N],id[N],vis[N];
 32 double minw[N];
 33 int n,m;
 34 
 35 inline double dist(Node &a,Node &b)
 36 {
 37     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 38 }
 39 
 40 double zhu_liu(int root)
 41 {
 42     int i,cou,u,v,k;
 43     double ans=0;
 44     while(1)
 45     {
 46         //init
 47         mem(pre,-1);
 48         for(i=1;i<=n;i++)minw[i]=DNF;
 49         for(i=0;i<m;i++){
 50             u=e[i].u;
 51             v=e[i].v;
 52             if(e[i].w<minw[v] && u!=v){
 53                 pre[v]=u;
 54                 minw[v]=e[i].w;
 55             }
 56         }
 57         pre[root]=-1;minw[root]=0;
 58         for(cou=0,i=1;i<=n;i++)
 59             if(pre[i]==-1 && i!=root)cou++;
 60             else ans+=minw[i];
 61         if(cou)return -1;
 62         //cheack the circle
 63         mem(vis,0);
 64         mem(id,0);
 65         for(i=1,k=0;i<=n;i++){
 66             if(id[i])continue;
 67             u=i;
 68             while(u!=-1 && !id[u] && vis[u]!=i){
 69                 vis[u]=i;
 70                 u=pre[u];
 71             }
 72             if(u!=-1 && !id[u] && vis[u]==i){
 73                 k++;
 74                 while(id[u]!=k){
 75                     id[u]=k;
 76                     u=pre[u];
 77                 }
 78             }
 79         }
 80         if(!k)break;
 81         for(i=1;i<=n;i++)if(!id[i])id[i]=++k;
 82         //eliminate circle
 83         for(i=0;i<m;i++){
 84             e[i].w-=minw[e[i].v];
 85             e[i].u=id[e[i].u];
 86             e[i].v=id[e[i].v];
 87         }
 88         n=k;
 89         root=id[root];
 90     }
 91     return ans;
 92 }
 93 
 94 int main()
 95 {
 96  //   freopen("in.txt","r",stdin);
 97     int i,j,a,b;
 98     double c,ans;
 99     while(scanf("%d%d",&n,&m)!=EOF)
100     {
101         for(i=1;i<=n;i++)
102             scanf("%lf%lf",&nod[i].x,&nod[i].y);
103         for(i=0;i<m;i++){
104             scanf("%d%d",&a,&b);
105             c=dist(nod[a],nod[b]);
106             e[i].u=a,e[i].v=b,e[i].w=c;
107         }
108 
109         ans=zhu_liu(1);
110         if(ans>=0)printf("%.2lf\n",ans);
111         else printf("poor snoopy\n");
112     }
113     return 0;
114 }

 

posted @ 2013-02-01 12:43  zhsl  阅读(808)  评论(0编辑  收藏  举报