分析(官方题解):

假设根已确定,可以发现新树若合法,需满足以下性质:根节点是n;儿子的值不大于父亲;具有相同值的节点形成一条链,并且链不会发生“分叉”(即有多个最低点)。所以对于新树中有出现的值x,原树在新树x链的最低点应为x,而其他新值为x的点,原值应小于x。那么我们先将所有链的最低点放上对应值,而空着的点和还没用的值进行配对。 贪心使答案字典序最小:从大到小枚举未用的值,用大根堆维护该值可以填入的位置id,取最大id填入。(否则,若某一步的值a匹配了非最大id x,而最大id y在后面配了值b,那么交换xy将产生更优解)。 还有一种方法是从大到小枚举空位置,填入 最接近小于 该位置新值的 未用的值。这用set是容易实现的。并且队友想出了使用并查集+双向链表的写法,可做到并查集复杂度(O(n*a(n)))。 不合法的情况除了不满足上述性质,还有就是匹配的过程中出现值或位置不够用。

然后考虑根的选择。由上所述,根的值一定是新树n链的两个端点之一。可以发现,无论选哪个做根,不影响其它链的上下方向及链之间的相对关系,即不影响合法性。因为没选的那一头一定填n,所以我们贪心地选择id小的端点做根(否则交换两个端点的值,将得到更优的答案)。当然也可以两个点都跑一遍。 (出题人写hint的时候,把自己绕晕了。不好意思。)

一点感想:这个题就是说原树是有根树(每个点有权值),新树每个节点的权值是其子树的最大值

由于是排列(也就是每个权值都不一样),所以只有链状,具体的分析见这一篇

http://blog.csdn.net/bblss123/article/details/52058959

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e5+;
int head[N],tot;
struct Edge{
int v,next;
}edge[N<<];
void add(int u,int v){
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int val[N],ret[N],d[N],n,T,color[N],fa[N],kase;
vector<int>s;
bool can[N];
bool dfs(int u){
int sp=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
if(v==fa[u])continue;
if(val[v]>val[u])return false;
else if(val[v]==val[u]){if((++sp)>)return false;}
fa[v]=u;
if(!dfs(v))return false;
}
if(!sp){color[val[u]]=u;ret[u]=val[u];can[val[u]]=false;}
return true;
}
bool solve(){
s.clear();scanf("%d",&n);tot=;
for(int i=;i<=n;++i)color[i]=head[i]=-,fa[i]=d[i]=,can[i]=true;
for(int i=;i<=n;++i){
scanf("%d",&val[i]);
if(val[i]==n)s.push_back(i);
}
for(int i=;i<n;++i){
int u,v;scanf("%d%d",&u,&v);
add(u,v);add(v,u);
if(val[u]==n&&val[v]==n)++d[u],++d[v];
}
if(!s.size())return false;
for(int i=;i<s.size();++i)
if(d[s[i]]<d[s[]]||d[s[i]]==d[s[]]&&s[i]<s[])
swap(s[i],s[]);
if(d[s[]]>)return false;
if(!dfs(s[]))return false;
priority_queue<int>q;
for(int i=n;i>;--i){
if(can[i]){
if(q.empty())return false;
ret[q.top()]=i;q.pop();
}
if(color[i]!=-){
int tmp=color[i];
while(val[fa[tmp]]==i){
q.push(fa[tmp]);
tmp=fa[tmp];
}
}
}
return true;
}
int main(){
scanf("%d",&T);
while(T--){
printf("Case #%d:",++kase);
if(!solve())printf(" Impossible\n");
else {
for(int i=;i<=n;++i)printf(" %d",ret[i]);
printf("\n");
}
}
return ;
}

HDU5764 After a Sleepless Night 树形乱搞题的更多相关文章

  1. CF_402C Searching for Graph 乱搞题

    题目链接:http://codeforces.com/problemset/problem/402/C /**算法分析: 乱搞题,不明白题目想考什么 */ #include<bits/stdc+ ...

  2. codeforces 653C C. Bear and Up-Down(乱搞题)

    题目链接: C. Bear and Up-Down time limit per test 2 seconds memory limit per test 256 megabytes input st ...

  3. codeforces 664B B. Rebus(乱搞题)

    题目链接: B. Rebus time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  4. codeforces 669D D. Little Artem and Dance(乱搞题)

    题目链接: D. Little Artem and Dance time limit per test 2 seconds memory limit per test 256 megabytes in ...

  5. hihocoder 1236(2015北京网络赛 J题) 分块bitset乱搞题

    题目大意: 每个人有五门课成绩,初始给定一部分学生的成绩,然后每次询问给出一个学生的成绩,希望知道在给定的一堆学生的成绩比这个学生每门都低或者相等的人数 因为强行要求在线查询,所以题目要求,每次当前给 ...

  6. AOJ.176 两数组最短距离 (乱搞题)

    两数组最短距离 点我挑战题目 题意分析 给出2个数组,让求出2个数组元素差的绝对值的最小值是多少. 我这里是o(m+n)的算法.首先对于第一个数组,让他的第一个元素和第二个元素比较,如果他的第一个元素 ...

  7. hdu 4112 Break the Chocolate(乱搞题)

    题意:要把一块n*m*k的巧克力分成1*1*1的单元,有两种操作方式:1,用手掰(假设力量无穷大),每次拿起一块,掰成两块小的:2,用刀切(假设刀无限长),可以把多块摆在一起,同时切开.问两种方式各需 ...

  8. AT2386 Colorful Hats (乱搞题,思维题)

    分情况讨论的神题... max不等于min + 1 或者不等于min,这种情况显然不存在. 如果都等于一个数 有两种情况: 互相独立,那么a[i]肯定==n-1 有相同的,那么a[i]一定不是独立的. ...

  9. hdu-5676 ztr loves lucky numbers(乱搞题)

    题目链接: ztr loves lucky numbers  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 65536/65536 K ( ...

随机推荐

  1. ElasticSearch小操之Marvel,Sense

    慢慢弄弄,说不好马上就要用呢,,, 嘿嘿 参考网址: http://es.xiaoleilu.com/ Elasticsearch 权威指南(中文版) 阅读地址:Elasticsearch权威指南(中 ...

  2. Java Socket 使用BufferedWriter和BufferedReader要注意readLine 以及换行标志的发送

    当接收的类使用的是BufferedReader,发送的类是BufferedWriter的时候,要注意发送的一行要有换行标识符. 请看下面一个例子,服务器接收不到客户端的信息. 服务器: import ...

  3. Java 网络编程 字符流的发送与接收 自定义数据边界

    在网络编程中,客户端调用了flush方法,就会将缓存在字符流中的文本发送给服务器,服务器该怎样判断客户端发送的文本已经结束了呢? 我们先看一个例子: 客户端: import java.io.IOExc ...

  4. 【转】Wireshark:“There are no interfaces on which a capture can be done ”

    linux环境下 两种解决方案:    第一种方法:使用root用户登陆        xiaoshancun@xiaoshancun-VM500:~$ sudo wireshark    第二种方法 ...

  5. 小心!#define max(a,b) a>b?a:b

    今天做oj的时候,定义了两个宏: //wrong code#define max_2(a,b) a>b?a:b #define max_3(a,b,c) (a>b?a:b)>c?(a ...

  6. qt外部数据传入实现动态的折线图绘制

    在嵌入式开发中,实现数据收集与显示很常见,对于希望数据稳定的应用来说,               折现图的表现形式很符合条件.               本实现是通过qt的signal-slot来 ...

  7. QT进度条QProgressBar的练习(定制QProgressBar,单独成为一个控件)

    progressbar.h #ifndef PROGRESSBAR_H #define PROGRESSBAR_H #include <QProgressBar> class QStrin ...

  8. 多线程+委托的安全访问(invoke)

    1.声明方法 2.声明委托类型 3.创建委托对象 4.启动线程 5.在线程调用的方法里通过Control的Invoke方法执行委托 public Form1() { InitializeCompone ...

  9. IDEA使用的点点滴滴

    查找一个类可以使用快捷键Ctrl + N 那么怎么看这个类中有哪些属性,哪些方法,就像Eclipse中的outline功能呢? 如查看NIO中的Buffer类,Ctrl + N-->

  10. 深度卷积神经网络用于图像缩放Image Scaling using Deep Convolutional Neural Networks

    This past summer I interned at Flipboard in Palo Alto, California. I worked on machine learning base ...