坑题...最开始题意理解错了...找了好长时间..和别人对拍数据才发现是题意理解错了..
已知在微博上的一条信息以及一些转发,转发一定是从原信息转发或者从某个转发转发,转发时会带一个自己的立场“赞”或“踩”。每个账户仅会转发一次,原账户不会转发。现在你可以反转某个账户的立场,反转立场后转自该账户的账户的立场也会被反转。反转一个账户的立场一次需要花费X。现在发现有一些账户是已经被别人反转过的,反转这些账户的立场需要的花费不是X而是Y。每个账户都有一个权值。求让你反转某些账户的立场后,所能够得到的"赞"账户权值和减去"踩"账户权值和再减去你的花费的最大值。
要注意题目里给出的立场时该账户的原始立场而不是被反转过的。别人反转某个账户的立场的时候,也是会将转发自该账户的账户的立场反转的...
数据范围:点的个数小于50000
因为每个账户不会转发两次,所以整个转发表构成了一棵树。对于每个点,记录两个值,dp1:不对其进行反转所能够得到的最高收益,dp2:对其反转所能够得到的最高收益(未记入当前点的反转花费)。状态转移方程见代码。
#include <cstdio>
#include <cstring>
inline int max(int a,int b) {
return a>b?a:b;
}
struct Node {
int fe,dp1,dp2,value,cost;
int fs,nb;
bool flag;
};
Node a[50010];
int p;
void befather(int son,int father) {
a[son].nb=a[father].fs;
a[father].fs=son;
}
void dfs(int i,bool notflip) {
if (a[i].flag==true) notflip=!notflip;
if (notflip) {
a[i].dp1=a[i].value;
a[i].dp2=-a[i].value;
} else {
a[i].dp2=a[i].value;
a[i].dp1=-a[i].value;
}
for (int j=a[i].fs;j!=0;j=a[j].nb) {
dfs(j,notflip);
a[i].dp1+=max(a[j].dp1,a[j].dp2-a[j].cost);
a[i].dp2+=max(a[j].dp2,a[j].dp1-a[j].cost);
}
}
int main() {
int n,x,y,i;
while (scanf("%d%d%d",&n,&x,&y)!=EOF) {
memset(a,0,sizeof(a));
p=1;
for (i=1;i<=n;i++) {
int from,s,p;
scanf("%d%d%d%d",&a[i].value,&from,&s,&p);
befather(i,from);
if (s) {
a[i].cost=y;
a[i].flag=true;
} else a[i].cost=x;
if (p) a[i].value=-a[i].value;
}
dfs(0,true);
if (a[0].dp1>=0) printf("%d\n",a[0].dp1);
else printf("HAHAHAOMG\n");
}
return 0;
}