poj Command Network 最小树形图

规定根节点,求一颗生成树使得权值最小,但由于是有向图,所以最小生成树算法失效。

查资料后得知此类问题叫做最小树形图。

解决最小树形图问题的朱刘算法,算法核心基于找 【最小弧集->找环,消环缩点】 的思想,来慢慢构造树形图。

所有的灵魂都在这张图上。0.0

注意缩点后的弧权值的处理

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
#define INF 0x3FFFFFF
#define MAXN 2222
#define eps 1e-6
bool zero(double x) {return x>=-eps&&x<=eps;}
struct edge
{
	int  u,v;
	double w;
}e[10005];
int n,en,m;
int pre[MAXN],id[MAXN],vis[MAXN];
double in[MAXN];
void add(int u,int v,double w)
{
	e[en].u=u;
	e[en].v=v;
	e[en++].w=w;
}
int zl(int root ,int vn)
{
	double ans=0;
	int cnt;
	while(1)
	{
		for(int i=0;i<vn;i++)
			in[i]=INF,id[i]=-1,vis[i]=-1;
		for(int i=0;i<en;i++)
		{
			if(in[e[i].v]>e[i].w && e[i].u!=e[i].v)
			{
				pre[e[i].v]=e[i].u;
				in[e[i].v]=e[i].w;
			}
		}
		in[root]=0;
		pre[root]=root;
		for(int i=0;i<vn;i++)
		{
			ans+=in[i];
			if(zero(in[i]-INF)){puts("poor snoopy");
				return -1;
			}
		}
		cnt=0;
		for(int i=0;i<vn;i++)
		{
			if(vis[i]==-1)
			{
				int t=i;
				while(vis[t]==-1)
				{
					vis[t]=i;
					t=pre[t];
				}
				if(vis[t]!=i || t==root) continue;
				for(int j=pre[t];j!=t;j=pre[j])
					id[j]=cnt;
				id[t]=cnt++;
			}
		}
		if(cnt==0) break;
		for(int i=0;i<vn;i++)
			if(id[i]==-1)
				id[i]=cnt++;
		for(int i=0;i<en;i++)
		{
			int u,v;
			u=e[i].u;
			v=e[i].v;
			e[i].u=id[u];
			e[i].v=id[v];
			e[i].w-=in[v];
		}
		vn=cnt;
		root=id[root];
	}
	printf("%.2lf\n",ans);
	return ans;
}
double x[105],y[105];
int main()
{
    int a,b;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf",&x[i],&y[i]);
        }
        en=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            a--;
            b--;
            double d=sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
            add(a,b,d);
        }
        zl(0,n);
    }
    return 0;
}

poj Command Network 最小树形图,布布扣,bubuko.com

时间: 2024-10-07 06:55:31

poj Command Network 最小树形图的相关文章

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 =

poj3134 Command Network --- 最小树形图

新单词unidirectional get T T 求有向图上,以某点为根的,最小生成树 参考别人的模板 #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<iostream> #include<algorithm> #include<cmath> #define inf 2000000000 using namespac

POJ 3164 Command Network(最小树形图)

Command Network Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 13817   Accepted: 3973 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:找环.找环找的是最小入边构成的新

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

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

POJ3164 Command Network 最小树形图

最小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T,并且T中所有边的总权值最小. 朱刘算法模板题 #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <stack> #include <

【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 最小树形图: 名词解释: 其实就是有向图

poj 3164(最小树形图)

有固定根的最小树形图求法O(VE): 首先消除自环,显然自环不在最小树形图中.然后判定是否存在最小树形图,以根为起点DFS一遍即可. 之后进行以下步骤. 设cost为最小树形图总权值. 0.置cost=0. 1.求最短弧集合Ao (一条弧就是一条有向边) 除源点外,为所有其他节点Vi,找到一条以Vi为终点的边,把它加入到集合Ao中. (加边的方法:所有点到Vi的边中权值最小的边即为该加入的边,记prev[vi]为该边的起点,mincost[vi]为该边的权值) 2.检查Ao中的边是否会形成有向圈

Poj 3164 Command Network【最小树形图】

Command Network Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 15914   Accepted: 4583 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