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

/*
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;
}

时间: 2024-12-18 19:16:52

poj 3164 最小树形图模板!!!的相关文章

poj 3164 最小树形图模板 (优先c++ ,g++ 有时会wa==)

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include <iostream> #define eps 1e-8 using namespace std; /* 最小树形图图模版-朱刘算法 模版说明:点标号必须0-(N-1) 必须去除到自身的点(到自身的边的边权赋无限大) */ #define M 109 #define type double

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

POJ 3164 Command Network(最小树形图模板题+详解)

http://poj.org/problem?id=3164 题意: 求最小树形图. 思路: 套模板. 引用一下来自大神博客的讲解:http://www.cnblogs.com/acjiumeng/p/7136604.html 算法步骤如下: 1.判断图的连通性,若不连通直接无解,否则一定有解. 2.为除了根节点以外的所有点选择一个权值最小的入边,假设用pre数组记录前驱,f数组记录选择的边长,记所选边权和为temp. 3.(可利用并查集)判断选择的的边是否构成环,若没有则直接$ans+=tem

无根最小树形图模板

1 #include<iostream> 2 using namespace std; 3 #include<cstdio> 4 #include<cstring> 5 #define MAXN 1005 6 #define INF 0x7f7f7f7f 7 typedef __int64 type; 8 struct node//边的权和顶点 9 { 10 int u, v; 11 type w; 12 }edge[MAXN * MAXN]; 13 int pre[M

最小树形图(模板)

本文链接:http://www.cnblogs.com/Ash-ly/p/5536796.html 定义: 设G = (V, E)是一个有向图,如果具有下述性质 (1)G中不包含有向环; (2)存在一个顶点vi,它不是任何弧的终点,而V的其它顶点都恰好是唯一的一条弧的终点.则称 G是以vi为根的树形图. 最小树形图就是有向图G = (V, E)中以vi为根的树形图中权值的和最小的那一个. 用朱刘算法求最小树形图: 最小树形图基于贪心和缩点的思想,所谓缩点,就是将几个点看成一个点,所有连到这几个点

【POJ3164】Command Network 最小树形图模板题 重修版

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44935891"); } 我以前的版本 算法构造过程以及傻叉代码+弱版注释见以前博客 http://blog.csdn.net/vmurder/article/details/38819711 最小树形图: 名词解释: 其实就是有向图

poj3164最小树形图模板题

题目大意:给定一个有向图,根节点已知,求该有向图的最小树形图.最小树形图即有向图的最小生成树,定义为:选择一些边,使得根节点能够到达图中所有的节点,并使得选出的边的边权和最小. 题目算法:朱-刘算法(即由中国人朱永津和刘振宏共同发明的算法). 算法步骤如下: 1.判断图的连通性,若不连通直接无解,否则一定有解. 2.为除了根节点以外的所有点选择一个权值最小的入边,假设用pre数组记录前驱,f数组记录选择的边长,记所选边权和为temp. 3.(可利用并查集)判断选择的的边是否构成环,若没有则直接a

朱、刘算法:求最小树形图权值个人理解+个人详解【最小树形图模板】

什么是最小树形图?相信大家如果会过来看这篇文章,想必也应该对最小生成树有所了解的,最小生成树求的是无向图的一颗生成树的最小权值.我们的最小树形图就是来解决一个有向图的一颗生成树的最小权值,对于度娘来说,最小树形图是这样定义的:最小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T,并且T中所有边的总权值最小. 通解最小树形图的一种算法是是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法:朱.刘算法. 今天我们就来浅谈一下最小树形图的问题. 大题上完整的朱

最小树形图模板 UVA11183

题意:给定n个节点m条边的有向带权图,求以0为根节点的最小树形图权值大小 1 #include<cstdio> 2 #include<algorithm> 3 #include<string.h> 4 using namespace std; 5 const int maxn=1e3+10; 6 const int maxm=4e4+10; 7 const int inf=0x3f3f3f3f; 8 int n,m; 9 int cost[maxn],pre[maxn]