POJ 3164最小树形图

  1 /*POJ 3164
  2 一个通信网络被破坏了
  3 给定每个点的坐标,和两两之间可修复的边和长度
  4 现在选择部分修通,使从1点出发可到达所有点,并且代价最短
  5 
  6 可看出是一个生成树的问题,做了UVA的那道,这道很简单了
  7 
  8 PS:unidirection 是有向
  9    undirecttion 才是无向
 10 C++交才可以
 11 */
 12 #include<iostream>
 13 #include<string.h>
 14 #include<stdio.h>
 15 #include<stdlib.h>
 16 #include<cmath>
 17 #include<algorithm>
 18 #include<queue>
 19 #include<stack>
 20 #include<set>
 21 #include<map>
 22 #define maxn 100+5
 23 #define maxe 20000+5
 24 #define typec double
 25 using namespace std;
 26 
 27 const typec inf=99999999;
 28 int nextint(){int x;scanf("%d",&x);return x;}
 29 int nextdou(){double x;scanf("%lf",&x);return x;}
 30 double X[maxn],Y[maxn];
 31 double Dis(int i,int j){
 32     double x1=X[i],x2=X[j],y1=Y[i],y2=Y[j];
 33     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
 34 }
 35 struct Edge{
 36     int u,v;
 37     typec c;//权值
 38 }edge[maxe];
 39 
 40 int vis[maxn],pre[maxn],id[maxn];
 41 typec in[maxn];
 42 typec zhuliu(int root,int nv,int ne){//最小树形图
 43       int i,j,u,v;
 44       typec ans=0;
 45       while(1){
 46               for(i=0;i<nv;i++)in[i]=inf;
 47               for(i=0;i<ne;i++){
 48                       u=edge[i].u;
 49                       v=edge[i].v;
 50                       if(u!=v&&edge[i].c<in[v]){
 51                               pre[v]=u;
 52                               in[v]=edge[i].c;
 53                       }
 54               }
 55               in[root]=0;
 56               for(i=0;i<nv;i++)if(fabs(in[i]-inf)<1e-6)return -1;
 57               int cnt=0;
 58               memset(id,-1,sizeof(id));
 59               memset(vis,-1,sizeof(vis));
 60               for(i=0;i<nv;i++){
 61                       v=i;
 62                       ans+=in[i];
 63                       while(vis[v]!=i&&id[v]==-1&&v!=root){
 64                               vis[v]=i;
 65                               v=pre[v];
 66                       }
 67                       if(v!=root&&id[v]==-1){
 68                               for(u=pre[v];u!=v;u=pre[u])id[u]=cnt;
 69                               id[v]=cnt++;
 70                       }
 71               }
 72               if(cnt==0)break;
 73               for(i=0;i<nv;i++)if(id[i]==-1)id[i]=cnt++;
 74               for(i=0;i<ne;i++){
 75                       v=edge[i].v;
 76                       edge[i].u=id[edge[i].u];
 77                       edge[i].v=id[edge[i].v];
 78                       if(edge[i].u!=edge[i].v)edge[i].c-=in[v];
 79               }
 80               nv=cnt;root=id[root];
 81       }
 82         return ans;
 83 }
 84 int n,m;
 85 int cnt;
 86 void built_tree(){
 87     cnt=0;
 88     for(int i=0;i<m;i++){
 89         int u=nextint(),v=nextint();
 90         u--,v--;
 91         double dis=Dis(u,v);
 92 //        cout<<u<<","<<v<<" dis="<<dis<<endl;
 93         edge[cnt].u=u;
 94         edge[cnt].v=v;
 95         edge[cnt++].c=dis;
 96 //        edge[cnt++]=(Edge){v,u,dis};
 97     }
 98 }
 99 int main(){
100 //    freopen("out.txt","w",stdout);
101     while(cin>>n>>m){
102         for (int i=0;i<n;i++){
103             X[i]=nextdou();
104             Y[i]=nextdou();
105         }
106         built_tree();
107         double ans=zhuliu(0,n,cnt);
108         if (ans<0) printf("poor snoopy
");else printf("%.2lf
",ans);
109     }
110     return 0;
111 }
原文地址:https://www.cnblogs.com/little-w/p/3597094.html