Problem
给出经过每个点的流量,0代表不确定,将整张图的各个点的流量输出,如果方案不唯一或者有的点最终流量<=0或者出现矛盾,输出impossible。
Solution
先确定叶子结点的流量,再向上确定其它结点的流量。记录每个点所能确定的其下叶子结点的总权值,如果其确定的叶子结点只有一个或确定的叶子结点数等于其能确定的总权值,就更新这部分叶子结点。
注意,一个叶子结点只由它最近的权值不为0的祖宗确定。
Code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=3e5+5;
int n,last[maxn],cnt,fa[maxn],f[maxn];//num:底下未赋值叶子结点数
long long p[maxn],consts[maxn],num[maxn];
struct edge
{
int v,next;
} e[maxn*2];
bool conf,islev[maxn];
inline void add(int u,int v)
{
e[++cnt].v=v;
e[cnt].next=last[u];
last[u]=cnt;
}
void dfs(int u)
{
long long pw=0;
for(int i=last[u]; i; i=e[i].next)
{
int v=e[i].v;
if(v==fa[u]) continue;
dfs(v);
}
for(int i=last[u]; i; i=e[i].next)
{
int v=e[i].v;
if(v==fa[u]) continue;
if(p[v]) pw+=p[v];
}
if(p[u]==0)
p[u]=pw;
if(pw&&p[u]!=pw||p[u]<=0) conf=1;
}
int dfs2(int u)
{
if(!islev[u])
{
if(!p[u])
num[u]++;
return p[u];
}
long long ans=0;
for(int i=last[u]; i; i=e[i].next)
{
int v=e[i].v;
if(v==fa[u]) continue;
long long tmp=dfs2(v);
if(!p[v])
{
ans+=tmp;
num[u]+=num[v];
}
else ans+=p[v];
}
consts[u]=p[u]-ans;
return ans;
}
int finds(int x)
{
if(!x) return 0;
return (x&&p[x])?x:f[x]=finds(f[x]);
}
int main()
{
cin>>n;
for(int i=2; i<=n; i++)
{
scanf("%d",&fa[i]);
add(i,fa[i]);
add(fa[i],i);
islev[fa[i]]=1;
}
for(int i=1; i<=n; i++)
f[i]=fa[i];
for(int i=1; i<=n; i++)
scanf("%d",&p[i]);
dfs2(1);
p[0]=0;
for(int i=1; i<=n; i++)
{
if(!islev[i]&&!p[i])
{
int x=finds(i);
if(!x) continue;
if(num[x]==1)
p[i]=consts[x];
else if(consts[x]==num[x])
p[i]=1;
}
}
dfs(1);
if(conf)
{
cout<<"impossible"<<endl;
init();
continue;
return 0;
}
for(int i=1; i<=n; i++)
cout<<p[i]<<endl;
init();
}
return 0;
}