周赛时遇到的一道比较有意思的题目:

Problem Statement

    

There are N rooms in Maki's new house. The rooms are numbered from 0 to N-1. Some pairs of rooms are connected by bidirectional passages. The passages have the topology of a tree. That is, there are exactly N-1 of them and it is possible to go from any room to any other room by following some sequence of passages.

You are given two vector <int>s a and b that describe the passages. For each valid i, there is a passage that connects the rooms a[i] and b[i]. You are also given an int s. The house has exactly one entrance from the outside, and the entrance leads to the room s.

Niko is helping Maki move into the new house. Maki has exactly N pieces of furniture. The pieces are numbered from 0 to N-1. Niko will carry them into the house in this order. Each piece of furniture must be placed into a different room. Maki does not care which piece goes where, each of the N! permutations is allowed.

However, not all of those N! permutations are actually possible. This is because the furniture is large. As soon as a room contains a piece of furniture, it is impossible to move other pieces through this room. Thus, Niko must place the furniture carefully. Formally, she can place a new piece of furniture into the room x if and only if all rooms on the (unique) path between s and x, including s and x, are still empty. Niko is smart and she will always place the furniture in such a way that she never gets stuck. Thus, at the end each of Maki's rooms will contain exactly one piece of furniture.

Calculate and return the number of ways how the furniture can be arranged in Maki's house at the end.

Definition

    
Class: OneEntrance
Method: count
Parameters: vector <int>, vector <int>, int
Returns: int
Method signature: int count(vector <int> a, vector <int> b, int s)
(be sure your method is public)

Limits

    
Time limit (s): 2.000
Memory limit (MB): 256
Stack limit (MB): 256

Constraints

- N will be between 1 and 9, inclusive.
- a and b will contain exactly N-1 elements each.
- Each element of a and b will be between 0 and N-1, inclusive.
- The graph described by a and b will be a tree.
- s will be between 0 and N-1, inclusive.

Examples

0)  
    
{0, 1, 2}
{1, 2, 3}
0
Returns: 1
There is only one solution: Niko must fill the rooms in the order {3,2,1,0}. Thus, piece number 0 will end in room 3, piece number 1 in room 2, and so on.
1)  
    
{0, 1, 2}
{1, 2, 3}
2
Returns: 3
In this case Niko can choose one of three orders: {3,0,1,2}, {0,3,1,2}, or {0,1,3,2}. Note that the room with the entrance (in this case, room 2) always gets the last piece of furniture.
2)  
    
{0, 0, 0, 0}
{1, 2, 3, 4}
0
Returns: 24
 
3)  
    
{7, 4, 1, 0, 1, 1, 6, 0}
{6, 6, 2, 5, 0, 3, 8, 4}
4
Returns: 896
 
4)  
    
{}
{}
0
Returns: 1
Maki's new house has only one room.

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.

这道题目也等同于:

假设一个Tree含有N个结点,现在有N个数字 1-N,将这个Tree的N个结点用这N个数字编号,要求父结点一定要大于子结点的编号,一共有多少种编号方式。

这种题目都可以抽象为一个问题:求一个Tree 所有结点的拓扑序列的个数。

求解方式可以用DFS来做:

另int Func() 表示当前Tree 的拓扑排序数量,Func() 可以这么计算:找到当前Tree中所有入度为0的结点,假设有K个这样的结点,对于每个这样的结点,从Tree去掉从该结点出发的边,然后算出去掉边后的Tree 对应的Func()。子Func()的结果的总和,就是 父Func()的结果。

当所有结点都遍历过时,Func() 返回 1

题目中的图表示是用两个vector 表示,所以要先根据这两个vector 构建出单向邻接矩阵 conn[][]

#include<iostream>
#include<vector>
#include<string.h>
using namespace std; class OneEntrance{
public:
int count(vector <int> a, vector <int> b, int s){
N = a.size() + ;
if(N <= ) return N;
memset(conn, , sizeof(conn));
memset(visit, , sizeof(visit));
dfsconn(a, b, s, -); //use a, b to create adjacency matrix(mono-directed)
return dfscount(conn); //based on matrix, get the total amount of topological sequence.
}
private:
bool conn[][];
bool visit[];
int N = ;
void dfsconn(vector<int> &a, vector<int> &b, int cur, int pre){
for(int i = ; i < a.size(); ++i){
if(a[i] == cur && b[i] != pre){
conn[a[i]][b[i]] = true;
dfsconn(a, b, b[i], cur);
}
if(b[i] == cur && a[i] != pre){
conn[b[i]][a[i]] = true;
dfsconn(a, b, a[i], cur);
}
}
}
int dfscount(bool conn[][]){
int i, j, zdgrcnt, cnt = ;
for(i = ; i < N; ++i) cnt += (!visit[i] ? : );
if(cnt == ) return ;
cnt = ;
for(i = ; i < N; ++i){
if(visit[i]) continue;
zdgrcnt = ;
for(j = ; j < N; ++j){
zdgrcnt += (conn[j][i] ? : );
}
if(zdgrcnt == ){ //found one node whose in-order degree is zero
visit[i] = true;
vector<bool> tmp(N, false);
for(j = ; j < N; ++j){
if(conn[i][j]){
tmp[j] = true;
conn[i][j] = false; //remove its out-order edge.
}
}
cnt += dfscount(conn);
for(j = ; j < N; ++j){
if(tmp[j]) conn[i][j] = true;
}
visit[i] = false;
}
}
return cnt;
}
};

dfs 中包含了很多重复计算,毕竟是递归。

动态规划的解法可以参考对 HDU 4661 这一题的解答

传送门: http://www.cnblogs.com/GBRgbr/p/3312866.html

求拓扑排序的数量,例题 topcoder srm 654 div2 500的更多相关文章

  1. Topcoder SRM 619 DIv2 500 --又是耻辱的一题

    这题明明是一个简单的类似约瑟夫环的问题,但是由于细节问题迟迟不能得到正确结果,结果比赛完几分钟才改对..耻辱. 代码: #include <iostream> #include <c ...

  2. hdu1532 用BFS求拓扑排序

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1285 题目给出一些点对之间的先后顺序,要求给出一个字典序最小的拓扑排列.对于拓扑排序的问题,我们有DF ...

  3. Topcoder Srm 673 Div2 1000 BearPermutations2

    \(>Topcoder \space Srm \space 673 \space Div2 \space 1000 \space BearPermutations2<\) 题目大意 : 对 ...

  4. Topcoder Srm 671 Div2 1000 BearDestroysDiv2

    \(>Topcoder \space Srm \space 671 \space Div2 \space 1000 \space BearDestroysDiv2<\) 题目大意 : 有一 ...

  5. TopCoder SRM 701 Div2 Problem 900 ThueMorseGame(博弈+预处理)

    题意  Alice和Bob在玩一个游戏,Alice先手. 每次一个人可以从一堆式子中拿走任意数量(不超过m)的式子. 取走最后一颗式子的人胜利. 当一个取完某一步的时候剩下的石子数量的二进制表示中1的 ...

  6. Topcoder SRM 626 DIV2 SumOfPower

    本题就是求所有连续子数列的和 开始拿到题目还以为求的时数列子集的和,认真看到题目才知道是连续子数列 循环遍历即可 int findSum(vector <int> array) { ; ; ...

  7. Topcoder SRM 626 DIV2 FixedDiceGameDiv2

    典型的条件概率题目. 事件A在另外一个事件B已经发生条件下的发生概率.条件概率表示为P(A|B),读作“在B条件下A的概率”. 若只有两个事件A,B,那么, P(A|B)=P(AB)/P(B) 本题的 ...

  8. topcoder SRM 610 DIV2 TheMatrix

    题目的意思是给一个01的字符串数组,让你去求解满足棋盘条件的最大棋盘 棋盘的条件是: 相邻元素的值不能相同 此题有点像求全1的最大子矩阵,当时求全1的最大子矩阵是用直方图求解的 本题可以利用直方图求解 ...

  9. topcoder SRM 624 DIV2 CostOfDancing

    排个序,求前k个元素和即可 int minimum(int K, vector <int> danceCost) { sort(danceCost.begin(),danceCost.en ...

随机推荐

  1. NSIS总结1——以管理权限运行

    在Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" 到第一个Section之间插入一行代码 RequestExecutionLevel admin ...

  2. iOS开发——高级技术&调用地图功能的实现

    调用地图功能的实现 一:苹果自带地图 学习如逆水行舟,不进则退.古人告诉我们要不断的反思和总结,日思则日精,月思则月精,年思则年精.只有不断的尝试和总结,才能让我们的工作和生活更加 轻松愉快和美好.连 ...

  3. MyEclipse使用总结——在MyEclipse中设置jsp页面为默认utf-8编码

    在MyEclispe中创建Jsp页面,Jsp页面的默认编码是“ISO-8859-1”,如下图所示: 在这种编码下编写中文是没有办法保存Jsp页面的,会出现如下的错误提示: 因此可以设置Jsp默认的编码 ...

  4. Maven学习总结(二)——Maven项目构建过程练习_转载

    上一篇只是简单介绍了一下maven入门的一些相关知识,这一篇主要是体验一下Maven高度自动化构建项目的过程 一.创建Maven项目 1.1.建立Hello项目 1.首先建立Hello项目,同时建立M ...

  5. ooj 1066 青蛙过河DP

    http://121.249.217.157/JudgeOnline/problem.php?id=1066 1066: 青蛙过河 时间限制: 1 Sec  内存限制: 64 MB提交: 58  解决 ...

  6. iOS开发拓展篇——如何把项目托管到GitHub

    iOS开发拓展篇——如何把项目托管到GitHub 说明:本文主要介绍如何把一个OC项目托管到Github,重操作轻理论. 第一步:先注册一个Github的账号,这是必须的 注册地址:Github官网注 ...

  7. JPA 不在 persistence.xml 文件中配置每个Entity实体类的2种解决办法

    在Spring 集成 Hibernate 的JPA方式中,需要在persistence配置文件中定义每一个实体类,这样非常地不方便,远哥目前找到了2种方法.   这2种方式都可以实现不用persist ...

  8. 转:MPlayer源代码分析

    一.Mplayer支持的格式 MPlayer是一个LINUX下的视频播放器,它支持相当多的媒体格式,无论在音频播放还是在视频播放方面,可以说它支持的格式是相当全面的. 视频格式支持:MPEG.AVI. ...

  9. 取消 virtualStore 注册表[启用和禁止 UAC虚拟化]

    近日发现,在win2008R2 x64下运行的服务器程序,其注册表读取路径为: [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\SZDomain\itvc1] 但是经 ...

  10. BootStrap安装

    1. 安装Node.js    http://nodejs.org/download/ 2. 加速NPM安装    npm install -g cnpm --registry=http://r.cn ...