zjnu1709 UZASTOPNI (bitset,树形dp)
2016-03-09 21:16
423 查看
Description
Petar is throwing a birthday party and he decided to invite some of the employees of his company where he is the CEO. Each employee, including Petar, has a unique label from 1 to N, and an accompanying type of jokes they tell Vi . Also, each employee of the
company except Petar has exactly one supervisor. Since Petar is the CEO of the company, he has the label 1 and is directly or indirectly superordinate to all the employees. At the birthday party, there are certain rules that all people present (including Petar)
must follow.
• At the party, there shouldn’t be two people that tell the same type of jokes.
• Person X cannot be invited if their direct supervisor is not invited.
• Person X cannot be invited if the set of jokes the invitees that person X is superior to (directly or indirectly) tell and person X don’t form a set of consecutive numbers.
The numbers in the set are consecutive if the difference between adjacent elements is exactly 1 when the set is sorted ascendingly. For example, (3, 1, 2) and (5, 1, 2, 4, 3). Petar wants to know how many different sets of jokes he can see at his party with
the listed constraints.
Input
The first line of input contains the integer N, (1 ≤ N ≤ 10 000). The second line of input contains N integers, the types of jokes person i tells, Vi, (1 ≤ Vi ≤ 100). Each of the following N-1 lines contains two integers A and B, (1 ≤ A, B ≤ N), denoting that
person A is directly superior to person B.
Output
The first and only line of output must contain the number of different sets of jokes that comply to the previously listed constraints.
Sample Input
4
2 1 3 4
1 2
1 3
3 4
4
3 4 5 6
1 2
1 3
2 4
6
5 3 6 4 2 1
1 2
1 3
1 4
2 5
5 6
Sample Output
6
3
10
题意:n个点形成一棵树,每一个点有自己的价值,让你在满足这3个条件的前提下找到总的方案数:1.一个节点的父亲节点没有选择时,该节点不能选择.2.选择的点构成的集合中不能存在相同价值的两个点.3.选择的任何一棵子树(包含本身)价值所构成的集合一定是连续的.
思路:可以递归求解,我们假设一个节点的子树都处理完了,那么先把子树中所有得到的可行的区间都记录下来,然后枚举所有左端点(1~100),然后找出可行的右端点,可以用bitset处理。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 600000
#define maxn 10050
#define l first
#define r second
int v[maxn];
vector<int>e[maxn]; //存储边
bitset<105>flag[maxn][105]; //flag[i][j]表示第i个节点左端点为j,右端点的方案数
vector<int>p[105]; //p[i]表示该节点子树中左端点为i的右端点们
vector<pair<int,int> >s[maxn]; //s[i]表示节点为i的符合条件的区间们
void dfs(int u)
{
int i,j,k,lo,re;
for(i=0;i<e[u].size();i++){
dfs(e[u][i]);
}
for(i=1;i<=100;i++)p[i].clear();
for(i=0;i<e[u].size();i++){
int v=e[u][i];
for(j=0;j<s[v].size();j++){
p[s[v][j].l ].push_back(s[v][j].r);
}
}
for(lo=100;lo>=1;lo--){
if(lo==v[u]){
flag[u][lo]|=flag[u][lo+1];
flag[u][lo].set(lo);
}
else{
for(i=0;i<p[lo].size();i++){
re=p[lo][i];
if(lo>v[u] || re<v[u]){
flag[u][lo]|=flag[u][re+1];
flag[u][lo].set(re);
}
}
}
for(re=lo;re<=100;re++){
if(flag[u][lo].test(re)==1 && lo<=v[u] && re>=v[u]){
s[u].push_back(make_pair(lo,re) );
}
}
}
}
int main()
{
int n,m,i,j,c,d;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++){
scanf("%d",&v[i]);
}
for(i=1;i<=n-1;i++){
scanf("%d%d",&c,&d);
e[c].push_back(d);
}
dfs(1);
printf("%d\n",s[1].size());
}
return 0;
}
Petar is throwing a birthday party and he decided to invite some of the employees of his company where he is the CEO. Each employee, including Petar, has a unique label from 1 to N, and an accompanying type of jokes they tell Vi . Also, each employee of the
company except Petar has exactly one supervisor. Since Petar is the CEO of the company, he has the label 1 and is directly or indirectly superordinate to all the employees. At the birthday party, there are certain rules that all people present (including Petar)
must follow.
• At the party, there shouldn’t be two people that tell the same type of jokes.
• Person X cannot be invited if their direct supervisor is not invited.
• Person X cannot be invited if the set of jokes the invitees that person X is superior to (directly or indirectly) tell and person X don’t form a set of consecutive numbers.
The numbers in the set are consecutive if the difference between adjacent elements is exactly 1 when the set is sorted ascendingly. For example, (3, 1, 2) and (5, 1, 2, 4, 3). Petar wants to know how many different sets of jokes he can see at his party with
the listed constraints.
Input
The first line of input contains the integer N, (1 ≤ N ≤ 10 000). The second line of input contains N integers, the types of jokes person i tells, Vi, (1 ≤ Vi ≤ 100). Each of the following N-1 lines contains two integers A and B, (1 ≤ A, B ≤ N), denoting that
person A is directly superior to person B.
Output
The first and only line of output must contain the number of different sets of jokes that comply to the previously listed constraints.
Sample Input
4
2 1 3 4
1 2
1 3
3 4
4
3 4 5 6
1 2
1 3
2 4
6
5 3 6 4 2 1
1 2
1 3
1 4
2 5
5 6
Sample Output
6
3
10
题意:n个点形成一棵树,每一个点有自己的价值,让你在满足这3个条件的前提下找到总的方案数:1.一个节点的父亲节点没有选择时,该节点不能选择.2.选择的点构成的集合中不能存在相同价值的两个点.3.选择的任何一棵子树(包含本身)价值所构成的集合一定是连续的.
思路:可以递归求解,我们假设一个节点的子树都处理完了,那么先把子树中所有得到的可行的区间都记录下来,然后枚举所有左端点(1~100),然后找出可行的右端点,可以用bitset处理。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 600000
#define maxn 10050
#define l first
#define r second
int v[maxn];
vector<int>e[maxn]; //存储边
bitset<105>flag[maxn][105]; //flag[i][j]表示第i个节点左端点为j,右端点的方案数
vector<int>p[105]; //p[i]表示该节点子树中左端点为i的右端点们
vector<pair<int,int> >s[maxn]; //s[i]表示节点为i的符合条件的区间们
void dfs(int u)
{
int i,j,k,lo,re;
for(i=0;i<e[u].size();i++){
dfs(e[u][i]);
}
for(i=1;i<=100;i++)p[i].clear();
for(i=0;i<e[u].size();i++){
int v=e[u][i];
for(j=0;j<s[v].size();j++){
p[s[v][j].l ].push_back(s[v][j].r);
}
}
for(lo=100;lo>=1;lo--){
if(lo==v[u]){
flag[u][lo]|=flag[u][lo+1];
flag[u][lo].set(lo);
}
else{
for(i=0;i<p[lo].size();i++){
re=p[lo][i];
if(lo>v[u] || re<v[u]){
flag[u][lo]|=flag[u][re+1];
flag[u][lo].set(re);
}
}
}
for(re=lo;re<=100;re++){
if(flag[u][lo].test(re)==1 && lo<=v[u] && re>=v[u]){
s[u].push_back(make_pair(lo,re) );
}
}
}
}
int main()
{
int n,m,i,j,c,d;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++){
scanf("%d",&v[i]);
}
for(i=1;i<=n-1;i++){
scanf("%d%d",&c,&d);
e[c].push_back(d);
}
dfs(1);
printf("%d\n",s[1].size());
}
return 0;
}
相关文章推荐
- DropDownMenu下拉筛选排序Menu
- linux启动流程
- Hadoop Distributed File System 简介
- 使用 Linux 和 Hadoop 进行分布式计算
- linux常用命令
- linux用户权限
- Linux用户和权限管理
- 关于tomcat版本造成的404的解决办法
- centos 编译 zeromq
- 【OpenGL】000 Visual Studio 2015 搭建OpenGL环境
- 插入排序之直接插入排序和Shell排序
- Hadoop 新 MapReduce 框架 Yarn 详解
- opencv 遍历图片像素并生成新图片(两种方式对比)
- Linux 的硬链接与软链接
- 一个专门下载全球气象站数据的网站(包括中国700多个站)
- tomcat nio与bio压测对比
- Linux操作系统基础(完结)
- 查看Nginx、apache、MySQL和PHP的编译参数
- linux与solaris命令区别
- linux学习笔记