bzoj1005

由于一些奇奇怪怪的事情忙了好一段时间没有静下心来写东西,一年区域赛快要开始的时候啦现在再开始写真的米有问题么··?虽然之前做了很多比赛 也写了很多题目,但是总是感觉状态只能算是soso~  无论如何还是好好努力一下吧!~  开始刷bzoj写点东西吧

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1005

看到这题的时候会觉得好像没有什么思路嘤嘤嘤,后来偷偷的去瞄了一眼题解233 知道了有prufer编码这个神奇的东西。

prufer的编码是通过度作为创建“序”的索引,通过构造方法使得最终的序与某棵树的形态一一对应。

从树上确定prufer编码的方法是:

1.选取树上度为1的编号最小的节点。

2.将(1)中所选出的节点相连的点加入prufer序列。

3.将(1)中所选出的节点删除。

4.若剩下的树只有一条边则返回 否则继续进行(1)



上图的prufer序列就是 2 2 1 3


而反过来 如果要通过prufer序列去求一棵树则采用以下步骤

1.通过prufer序列求出每个节点的度数【获得度数表】。

2.(对于第i次操作)查找度数表中度数为1且编号最小的节点 ,将之与prufer序列中的第i个节点连边

3.将(2)中度数表中的点与prufer序列中的点的度数都减1

4.若度数表中仅剩两个元素度数非0将之连边,否则返回2




类似这样的一个过程,当然这题知道了这个过程之后,就可以将问题转化为:对于那些已经明确知道度数为多少的节点poi[i] 

如果poi[i]==1 说明他们是叶节点 不可能出现在prufer序列中 反之需要求

∏C(left_position,poi[i]-1

对于度数不确定的,如果还有left_position个位置可以提供自每个位置上对于任何度数不确定的都是一种选择
则该题理论可解
import java.math.BigInteger;
import java.util.Scanner;


public class Main {

	/**
	 * @param args
	 */
	static BigInteger C(int dow,int upe){
		BigInteger ret=new BigInteger("1");
		for (int c_i=dow;c_i>=dow-upe+1;c_i--)
			ret=ret.multiply(BigInteger.valueOf(c_i));
		for (int c_i=upe;c_i>=1;c_i--)
			ret=ret.divide((BigInteger.valueOf(c_i)));
		return (ret);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		BigInteger ans;
		Scanner sc=new Scanner(System.in);
		int a[]=new int[1500];
		int n=sc.nextInt();
		int sum=0,cnt=0;
		for (int i=0;i<n;i++){
			a[i]=sc.nextInt();
			if (a[i]!=-1)
				sum+=a[i];
			else
				cnt++;
		}
		if (sum-n>n-2){
			System.out.println(-1);
			return;
		}
		ans=BigInteger.valueOf(1);
		int now=n-2;
		for (int i=0;i<n;i++)
			if (a[i]!=-1 && a[i]>1){
				if ((a[i]-1)*2<=now)
					ans=ans.multiply(C(now,a[i]-1));
				else
					ans=ans.multiply(C(now,now-(a[i]-1)));
				now=now-(a[i]-1);
			}
		for (int i=0;i<now;i++)
			ans=ans.multiply(BigInteger.valueOf(cnt));
		System.out.println(ans.toString());
	}

}

从这道题目的话感觉 对于树的记数其实都需要一个“序”,把一棵树对应成一个线性的结构才能比较好的进行操作。

如:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=58612#problem/F 这道题的因为要对一棵树的子树进行操作,所以选择用先序遍历将其转变成线性结构,他的要求是某一棵树的子树需要是处于线性结构区间中连续的一段,之后可以比较方便的用线段树进行区间操作 查询等内容进行求解。

再如:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 这道题目是典型的树分治,需要用树链剖分进行求解,现在想起来,其实树链剖分也是一种线性的序,他的要求是重链需要处在线性结构区间中连续的一段,之后同样用线段树进行求解。

因此由此感觉 树的记数基本上是需要通过转化结构完成的。


如果以上有哪点说的不对的 ~还请诸位看官多多指正! 感激不尽



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值