您的位置:首页 > 其它

bzoj 2799 [Poi2012]Salaries 贪心

2016-11-16 10:05 330 查看
感觉自己语文水平捉鸡,粘一下吴大爷的题解吧。。。



我们维护以每一个节点为根的子树内部有多少个没有确定权值的点,另外,我们利用一个数组维护每个权值已经给了哪个节点.

我们从小到大遍历每个权值,若这个权值当前并没有确定给哪个节点,则将其压入栈中;否则我们在对应节点的子树中进行一系列确定操作:

我们维护栈中有多少个权值,以及有多少个自由权值.(这个是什么一会再说)

若未确定的节点数正好等于当前的自由权值数与栈中的权值总数,显而易见这些权值都应该分配给这棵子树.但是只有只有一个儿子的情况才能确定这个权值.所以我们不断在链上去找即可.这个过程可能确定了一些权值,随后我们将栈清空,并令自由权值的数目为0.因为他们只能被拘束在这颗子树内,而不能去别的地方.

若不然,我们将自由权值及栈中的权值分配给这棵子树所需要的数目,剩下的全部变成自由权值.

我们发现栈中的权值和自由权值很像,但是为什么不都搞成自由权值,而是非要维护一个栈呢?

这个问题显而易见:自由权值都是可以互相交换的(等价的),而栈中的元素显然不是!



#include <bits/stdc++.h>
using namespace std;
#define N 1000010
int n,root,top;
vector<int>vec
,pos
;
int val
,fa
,use
,size
,st
;
queue<int>que;
void get(int x)
{
while(top)
{
val[x]=st[top--];
if(vec[x].size()!=1)return;
x=vec[x][0];
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&fa[i],&val[i]);
if(fa[i]==i)root=i,val[i]=n;
else vec[fa[i]].push_back(i);
use[val[i]]=1;
}
que.push(root);
while(!que.empty())
{
int t=que.front();que.pop();
st[++top]=t;size[t]=1;
for(int i=0;i<vec[t].size();i++)
que.push(vec[t][i]);
}
for(int i=top;i>=1;i--)
{
for(int j=0,t;j<vec[st[i]].size();j++)
{
size[st[i]]+=size[t=vec[st[i]][j]];
if(!val[t])
pos[val[st[i]]].push_back(t);
}
}
int cnt=0,p,rem=0,sum=0;
top=0;
for(int i=1;i<=n;i++)
{
if(!use[i])st[++top]=i;
else
{
int t=pos[i].size();
cnt+=t;if(t)p=pos[i][0];
for(int j=0;j<t;j++)
sum+=size[pos[i][j]];
if(!use[i+1])
{
if(!cnt)continue;
rem=top+rem-sum;
if(cnt==1&&!rem)get(p);
sum=0;cnt=0;top=0;
}
}
}
for(int i=1;i<=n;i++)
printf("%d\n",val[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: