[HDOJ 4896] Minimal Spanning Tree [最小生成树]

69 篇文章 0 订阅
23 篇文章 0 订阅

题目给出了一个图,每个点和他的前后5个点连边,边的权值是由一个公式计算得出的。求最小生成树的边权和。

我们观察公式,发现其有一个循环节,为54。就是说点i上的边的权值和点i+54上的边的权值是完全相同的。然后我们就可以把这个图缩成5+54+54+53+5这么多个点的图,求最小生成树了。

左右的5是因为这5个点和其他点不同,其左右不是都有5条边。第一个54为添加不需重复的边准备,即可能有一些边是不需要和循环节一起重复很多次的。第二个54为循环节的54。后边的53为剩余的53,即总点数减去10然后模54的余数。

然后就是求最小生成树,对边排序后按序添加。如果两条边权值一样,那么将不是循环节的那条(即不会被复制多次的)放在前边,求最小生成树之后计算结果的时候,要将是循环节的边乘以循环节的个数,即拷贝多份。

标准解法不是这样..是DP+矩阵加速...现在这个解法我没有严格的证明..不过感觉上是对的,并且也A了...

#include <cstdio>
#include <algorithm>
#include <iostream>

using namespace std;

const int mod=2333333;

const int XX=5;
inline bool notin(int i) {
	if (i<=XX+54||i>XX+54+54) return true;
	return false;
}
struct Edge {
	int x,y;
	long long v;
	void clear(int xx,int yy,long long vv) {
		x=xx;y=yy;v=vv;
	}
	friend bool operator < (const Edge &a,const Edge &b) {
		if (a.v!=b.v) return a.v<b.v;
		if (notin(a.x)) return true;
		return false;
	}
};
struct DisjoinSet {
	int a[600];
	void clear(int n) {
		for (int i=1;i<=n;i++) a[i]=i;
	}
	int get(int i) {
		if (a[i]==i) return i;
		return a[i]=get(a[i]);
	}
	void tosame(int x,int y) {
		x=get(x);
		y=get(y);
		a[x]=y;
	}
};

DisjoinSet c;
Edge b[1000];
int bp,n,pp;
long long ans;

int main() {
	int i,j,seed;
	while (scanf("%d%d",&n,&seed)!=EOF) {
		pp=1;
		while (n-54>=54+54+XX+XX) {
			n-=54;
			pp++;
		}
		c.clear(n);
		bp=0;
		long long x=seed;
		for (i=2;i<=n;i++) {
			x=x*907%mod;
			long long t=x;
			for (j=max(1,i-5);j<i;j++) {
				x=x*907%mod;
				long long w=t^x;
				b[bp++].clear(i,j,w);
			}
		}
		sort(b,b+bp);
		ans=0;
		for (i=0;i<bp;i++) {
			if (c.get(b[i].x)!=c.get(b[i].y)) {
				c.tosame(b[i].x,b[i].y);
				if (notin(b[i].x)) ans+=b[i].v;
				else ans+=b[i].v*pp;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值