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
const type inf=1e20;
struct Node{
	int u , v;
	type cost;
}E[M*M+5];
int pre[M],ID[M],vis[M];
type In[M];
type Directed_MST(int root,int NV,int NE) {
	type ret = 0;
	while(true) {
		//1.找最小入边
		for(int i=0;i<NV;i++) In[i] = inf;
		for(int i=0;i<NE;i++){
			int u = E[i].u;
			int v = E[i].v;
			if(E[i].cost < In[v] && u != v) {
				pre[v] = u;
				In[v] = E[i].cost;
			}
		}
		for(int i=0;i<NV;i++) {
			if(i == root) continue;
			if(In[i] == inf)	return -1;//除了跟以外有点没有入边,则根无法到达它
		}
		//2.找环
		int cntnode = 0;
	memset(ID,-1,sizeof(ID));
	memset(vis,-1,sizeof(vis));
		In[root] = 0;
		for(int i=0;i<NV;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] = cntnode;
				}
				ID[v] = cntnode ++;
			}
		}
		if(cntnode == 0)	break;//无环
		for(int i=0;i<NV;i++) if(ID[i] == -1) {
			ID[i] = cntnode ++;
		}
		//3.缩点,重新标记
		for(int i=0;i<NE;i++) {
			int v = E[i].v;
			E[i].u = ID[E[i].u];
			E[i].v = ID[E[i].v];
			if(E[i].u != E[i].v) {
				E[i].cost -= In[v];
			}
		}
		NV = cntnode;
		root = ID[root];
	}
	return ret;
}
int n,m;
struct Tpoint
{
	double x,y;
	void in()
	{
		scanf("%lf%lf",&x,&y);
	}
}p[M];
double dis(Tpoint a,Tpoint b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void init()
{
	for(int i=0;i<n;++i)p[i].in();
	int h=0;
	for(int i=0;i<m;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		if(x==y)continue;
		x--;y--;
		E[h].u=x;
		E[h].v=y;
		E[h++].cost=dis(p[x],p[y]);
	}
	double ans=Directed_MST(0,n,h);
	if(ans==-1)puts("poor snoopy");
	else
		printf("%.2f\n",ans);
}
int main() {
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		init();
	}
	return 0;
}

自己了一份== g++ wa  c++ ac
#include<iostream>
#include<cstring>
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<algorithm>
#include<stdio.h>
#include<iomanip>

#define rep(i,n) for(int i=0;i<n;++i)
#define fab(i,a,b) for(int i=a;i<=b;++i)
#define fba(i,b,a) for(int i=b;i>=a;--i)
#define PB push_back
#define MP make_pair
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define sf scanf
#define pf printf
#define LL long long
const int N=105;
using namespace std;
typedef pair<int,int>PII;
#define type double
const type inf = 1e20;
#define eps 1e-8
struct Edge{
    int u,v;
    type cost;
}E[N*N+10];
int pre[N],ID[N],vis[N];
type In[N];
type MST(int root,int n,int m){
    type ret=0;
    while(true){
        rep(i,n)In[i]=inf;
        rep(i,m){
            int u=E[i].u;
            int v=E[i].v;
            if(E[i].cost < In[v] && u!=v ){
                pre[v]=u;
                In[v]=E[i].cost;
            }
        }
        rep(i,n){
            if(i==root)continue;
            if(In[i]==inf)return -1;
        }
        int cntnode=0;
        memset(ID,-1,sizeof ID);
        memset(vis,-1,sizeof vis);
        In[root]=0;
        rep(i,n){
            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]=cntnode;
                }
                ID[v]=cntnode++;
            }
        }
        if(cntnode==0)break;
        rep(i,n)if(ID[i]==-1)ID[i]=cntnode++;
        rep(i,m){
            int v=E[i].v;
            E[i].u=ID[E[i].u];
            E[i].v=ID[E[i].v];
            if(E[i].u!=E[i].v)E[i].cost-=In[v];
        }
        n=cntnode;
        root=ID[root];
    }
    return ret;
}
int n,m;
struct Point{
    double x,y;
    void in(){
        sf("%lf%lf",&x,&y);
    }
}p[N];
double dis(Point a,Point b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void init(){
    rep(i,n)p[i].in();
    int h=0;
    rep(i,m){
        int x,y;
        sf("%d%d",&x,&y);
        if(x==y)continue;
        x--;y--;
        E[h].u=x;
        E[h].v=y;
        E[h++].cost=dis(p[x],p[y]);
    }
    double ans=MST(0,n,h);
    if(ans<0)puts("poor snoopy");
    else pf("%.2lf\n",ans+eps);
}
int main(){
    while(sf("%d%d",&n,&m)!=EOF){
        init();
    }
    return 0;
}
				
时间: 2024-08-06 21:54:20

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

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,doub

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

最小树形图(模板)

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

poj3164最小树形图模板题

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

无根最小树形图模板

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

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

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

什么是最小树形图?相信大家如果会过来看这篇文章,想必也应该对最小生成树有所了解的,最小生成树求的是无向图的一颗生成树的最小权值.我们的最小树形图就是来解决一个有向图的一颗生成树的最小权值,对于度娘来说,最小树形图是这样定义的:最小树形图,就是给有向带权图中指定一个特殊的点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]