码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3164 最小树形图模板!!!

时间:2014-08-27 18:52:24      阅读:307      评论:0      收藏:0      [点我收藏+]

标签:io   for   amp   on   size   ad   算法   ef   c   

/*
tle十几次,最后发现当i从1开始时,给环赋值时要注意啊!
最小树形图 
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 110
#define inf 0x3fffffff
#define eps 1e-10
struct node {
int u,v;
double w;
}edge[N*N*2];
double distance (double x,double y,double xx,double yy) {
return sqrt(1.0*(x-xx)*(x-xx)+1.0*(y-yy)*(y-yy));
}
int visit[N],id[N],pre[N],yong,n;
double dis[N];
void addedge(int u,int v,double w){
edge[yong].u=u;
edge[yong].v=v;
edge[yong++].w=w;
}
double  zhuliu(int root) {//朱刘算法模板
 double sum=0;
 while(1) {
        int i;
    for(i=0;i<n;i++)
        dis[i]=inf;
        memset(id,-1,sizeof(id));
        memset(visit,-1,sizeof(visit));
        for(i=0;i<yong;i++) {
            int u=edge[i].u,v=edge[i].v;
            if(dis[v]>edge[i].w&&u!=v){
                pre[v]=u;
                dis[v]=edge[i].w;
              //  if(u==root)//记录最后与根节点连接的边
              //      index=i;
            }
        }
       pre[root]=root;
        dis[root]=0;
        for(i=0;i<n;i++) {
                if(i==root)continue;
            if(dis[i]==inf)return -1;
            sum+=dis[i];
        }
        int res=0;
        for(i=0;i<n;i++) {
            int v=i;
            while(visit[v]!=i&&id[v]==-1&&v!=root) {
                visit[v]=i;
              v=pre[v];
            }
         if(v!=root&&id[v]==-1) {
            int u;
            for(u=pre[v];u!=v;u=pre[u])
                id[u]=res;
            id[v]=res++;//如果下标从1开始不能这么写了
         }
        }
        if(res==0)
            break;
        for(i=0;i<n;i++) {
            if(id[i]==-1)
                id[i]=res++;//同上
        }
        for(i=0;i<yong;i++) {
            int v=edge[i].v;
            edge[i].u=id[edge[i].u];
            edge[i].v=id[edge[i].v];
            if(edge[i].u!=edge[i].v)
                edge[i].w-=dis[v];
        }
        n=res;root=id[root];
 }
 return sum;
}

int main() {
   int m,i,j;
   double k,a[N],b[N];
   while(scanf("%d%d",&n,&m)!=EOF) {
    for(i=1;i<=n;i++)
        scanf("%lf%lf",&a[i],&b[i]);
        yong=0;
        while(m--) {
            scanf("%d%d",&i,&j);
            addedge(i-1,j-1,i==j?inf:distance(a[i],b[i],a[j],b[j]));
        }
        k=zhuliu(0);
    if(k<0)
        printf("poor snoopy\n");
    else
        printf("%.2f\n",k);
   }
return 0;
}
/*
下标是1-n;
如果是for(i=1;i<n;i++)还要注意n=res+1。所以模板不能乱改啊
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 110
#define inf 0x3fffffff
#define eps 1e-10
struct node {
int u,v;
double w;
}edge[N*N*2];
double distance (double x,double y,double xx,double yy) {
return sqrt(1.0*(x-xx)*(x-xx)+1.0*(y-yy)*(y-yy));
}
int visit[N],id[N],pre[N],yong,n;
double dis[N];
void addedge(int u,int v,double w){
edge[yong].u=u;
edge[yong].v=v;
edge[yong++].w=w;
}
double  zhuliu(int root) {//朱刘算法模板
 double sum=0;
 while(1) {
        int i;
    for(i=1;i<=n;i++)
        dis[i]=inf;
        memset(id,-1,sizeof(id));
        memset(visit,-1,sizeof(visit));
        for(i=0;i<yong;i++) {
            int u=edge[i].u,v=edge[i].v;
            if(dis[v]>edge[i].w&&u!=v){
                pre[v]=u;
                dis[v]=edge[i].w;
              //  if(u==root)//记录最后与根节点连接的边
              //      index=i;
            }
        }
       pre[root]=root;
        dis[root]=0;
        for(i=1;i<=n;i++) {
                if(i==root)continue;
            if(dis[i]==inf)return -1;
            sum+=dis[i];
        }
        int res=0;
        for(i=1;i<=n;i++) {
            int v=i;
            while(visit[v]!=i&&id[v]==-1&&v!=root) {
                visit[v]=i;
              v=pre[v];
            }
         if(v!=root&&id[v]==-1) {
            int u;
            id[v]=++res;
            for(u=pre[v];u!=v;u=pre[u])
                id[u]=res;
         }
        }
        if(res==0)
            break;
        for(i=1;i<=n;i++) {
            if(id[i]==-1)
                id[i]=++res;
        }
        for(i=0;i<yong;i++) {
            int v=edge[i].v;
            edge[i].u=id[edge[i].u];
            edge[i].v=id[edge[i].v];
            if(edge[i].u!=edge[i].v)
                edge[i].w-=dis[v];
        }
        n=res;root=id[root];
 }
 return sum;
}

int main() {
   int m,i,j;
   double k,a[N],b[N];
   while(scanf("%d%d",&n,&m)!=EOF) {
    for(i=1;i<=n;i++)
        scanf("%lf%lf",&a[i],&b[i]);
        yong=0;
        while(m--) {
            scanf("%d%d",&i,&j);
            addedge(i,j,i==j?inf:distance(a[i],b[i],a[j],b[j]));
        }
        k=zhuliu(1);
    if(k<0)
        printf("poor snoopy\n");
    else
        printf("%.2f\n",k);
   }
return 0;
}


poj 3164 最小树形图模板!!!

标签:io   for   amp   on   size   ad   算法   ef   c   

原文地址:http://blog.csdn.net/u011483306/article/details/38873105

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