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

朱刘算法模板题

#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;
}
时间: 2024-10-09 13:56:12

poj 3164 最小树形图(朱刘算法)的相关文章

POJ 3164 Command Network 最小树形图-朱刘算法裸题

题目来源:POJ 3164 Command Network 题意:求以1为根的最小树形图 没有输出字符串 思路:直接高朱刘算法 不懂的可以百度 学会了就是直接套模板的事情 其实就是不断消圈而已 不构成圈就有解 无法从根到达其他点就无解 #include <cstdio> #include <cstring> #include <cmath> const int maxn = 110; const int maxm = 50010; const double INF =

【POJ 3164】【朱刘算法模板】Command Network

Command Network Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 13977   Accepted: 4012 Description After a long lasting war on words, a war on arms finally breaks out between littleken's and KnuthOcean's kingdoms. A sudden and violent a

POJ 3164 Command Network (最小树形图-朱刘算法)

题目地址:POJ 3164 最小树形图第一发. 把一个v写成u了.....TLE了一晚上...(虽说今晚出去玩了..) 刚开始看这个算法的时看模板以为又是一个isap....吓得一个哆嗦.但是仔细看了看之后发现还是挺好理解的.写下自己的理解. 朱刘算法其实只有3步,然后不断循环. 1:找到每个点的最小入边.既然是生成树,那么对于每个点来说,只要选一个权值最小的入边就可以了.贪心思想.因为如果不是最小入边,那么它肯定不是最小树形图的一条边,考虑它是没有意义的. 2:找环.找环找的是最小入边构成的新

图论--最小树形图朱刘算法模板

最小树形图就是一个有向图,从根节点可以到达其他所有节点,而除根节点外的每个节点又有且仅有一个父节点,这样一张边权和最小的图就是最小树形图. 最小树形图有它特有的算法,朱刘算法.原理是先对除根节点以外的所有节点先找寻一条最小入边,接着判图中是否有有向环,如果有,将每个环缩成一点,再对这些点重新找最小入边,重复合并操作直至没有环. 我用的主要是从kuangbin巨巨的模板小改得到的昂. 各种注释便于理解: 1 #include<stdio.h> 2 #include<string.h>

&ldquo;Hdu4966&rdquo; GGS-DDU - 最小树形图/朱刘算法

原文引用https://www.dazhuanlan.com/2019/08/26/5d6302f8c23db/ 题目链接:传送门 Description 有一个人,想学习N个科目,每个科目都有相应的层次 有M个课程,M个课程的要求是,你的第c个科目的层次要达到l1,才可以参加,参加完这个课程后,你需要缴费money,但你的第d个科目的层次会达到l2 问如何花最少的钱,使得每个科目的层次都达到最高 Solution 每个科目的每个层次都看成一个点,每个科目的层次0和一个根连边,费用为0:每个科目

POJ - 3164 Command Network(朱刘算法)

题目大意:有N个点,M条有向边.现在要求你以1为根,构造出一棵最小生成树,问这棵最小生成树能否被构造出来,如果可以,总权值是多少 解题思路:朱刘算法的裸题,我只想吐槽一下POJ,用的是double型的,输出时是%.2lf,结果是WA 换成了%.2f就A了..这什么情况,白白花费了1个多小时去调错.. #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define N 1

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

Command Network Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 14340   Accepted: 4118 Description After a long lasting war on words, a war on arms finally breaks out between littleken’s and KnuthOcean’s kingdoms. A sudden and violent a

POJ - 3164-Command Network 最小树形图——朱刘算法

POJ - 3164 题意: 一个有向图,存在从某个点为根的,可以到达所有点的一个最小生成树,则它就是最小树形图. 题目就是求这个最小的树形图. 参考资料:https://blog.csdn.net/txl199106/article/details/62045479 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <strin

HDU 4966 GGS-DDU (最小树形图-朱刘算法)

题目地址:HDU 4966 刚开始没看清总级别只有500这一条件,看成了每一个都是500..然后建图思路就想歪了.....后来才发现是总共只有500..那么建图就很简单了..把每个科目的每个等级都设为一个点,把所有的0等级设为同一个树根.然后把所有科目的高等级向低等级连一条权值为0的有向边,第一个作用是保证最后的最小树形图是所有点都可达,第二个作用是保证每节课的的所需等级,只要达到高等级,那么使低等级也符合.然后再对每节课连边即可. 代码如下: #include <iostream> #inc

TJU 2248 Channel Design (最小树形图-朱刘算法)

题目地址:TJU 2248 最小树形图模板题.熟练一下模板. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h>