码迷,mamicode.com
首页 > 编程语言 > 详细

poj 3164 最小树形图(朱刘算法)

时间:2015-08-07 22:14:39      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

朱刘算法模板题

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define INF 1<<30

using namespace std;

int n,m;
struct node
{
    double x,y;
}nod[110<<1];
double in[110<<1] ;
int pre[110<<1] , id[110<<1] ,vis[110<<1];
struct edge{
    int u,v;
    double w;
}e[110*110];
double calcu_dis(int x,int y)
{
    return sqrt( (nod[x].x - nod[y].x) * (nod[x].x - nod[y].x) + (nod[x].y - nod[y].y) * (nod[x].y - nod[y].y)) ;
}
void makemap()
{
    for(int i=0;i<m;i++){
        scanf("%d%d",&e[i].u,&e[i].v) ;
        e[i].u--,e[i].v-- ;
        if(e[i].u == e[i].v) e[i].w=INF;
        else e[i].w=calcu_dis(e[i].u , e[i].v);
    }
}

double Direct_Mst(int root)
{
    double ret = 0;
    while(1){
        for(int i=0;i<n ;i++) in[i] = INF ;
        for(int i=0;i<m;i++){
            int u = e[i].u ;
            int v = e[i].v ;
            if(e[i].w<in[v] && u!=v){
                pre[v]= u;
                in[v]=e[i].w ;
            }
        }
        //判断能否遍历
        for(int i=0;i<n;i++){
            if(i!=root && in[i]==INF){
                return -1;
            }
        }
        //找环
        int cnt= 0;
        memset(id, -1 ,sizeof id) ;
        memset(vis , -1 , sizeof vis) ;
        in[root] = 0;
        for(int i=0;i<n;i++){
            ret += 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] = cnt;
                }
                id[v] = cnt++;
            }
        }
        if(cnt == 0){
            break;   //没有环
        }
        for(int i= 0;i<n ;i++){
            if(id[i] == -1){
                id[i] = cnt++;
            }
        }
        //有环则缩点重新标记
        for(int i=0 ;i<m;i++){
            int v=e[i].v;
            int u=e[i].u;
            e[i].u=id[u];
            e[i].v=id[v];
            if(e[i].u != e[i].v) e[i].w-=in[v] ;
        }
        n=cnt;
        root = id[root] ;
    }
    return ret ;
}

double solve()
{
    makemap() ;
    double ret = Direct_Mst(0) ;
    return ret ;
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        for(int i=0;i<n;i++){
            cin>>nod[i].x>>nod[i].y;
        }

        double ans=solve() ;
        if(ans == -1){
            printf("poor snoopy\n") ;
        }
        else {
            printf("%.2f\n",ans) ;
        }
    }
    return 0;
}

 

poj 3164 最小树形图(朱刘算法)

标签:

原文地址:http://www.cnblogs.com/Scale-the-heights/p/4711940.html

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