御坂和她的n-1个克隆姐姐(编号1~n-1)构成一张御坂网络,如果第x号"姐姐"和第y号"姐姐"有条x到y的有向边,则说明x可以将信息传给y,已知御坂妹妹作为n号点,是所有信息的源头,如果屏蔽掉x点之后y点无法得到御坂妹妹的信息,那么说明x是y的支配点,对于所有的点,求出它所有支配点的编号和(包括她自身的编号)
特殊的:如果x点本身就得不到信息,该点输出0
支配树模板题
注意不用新建节点,直接将n作为支配树的根,对于在支配树中的点,答案就是该点到根的编号和,
对于不在支配树中的点,答案为0
模板:
#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
#define LL long long
LL n, cnt, sdom[60005], idom[60005], key[60005], rak[60005];
LL dfn[60005], ufs[60005], fa[60005], val[60005];
vector<LL> G[60005], Gp[60005], Z[60005], Sp[60005];
LL Find(LL p)
{
LL temp;
if(ufs[p]==p)
return p;
temp = Find(ufs[p]);
if(sdom[key[ufs[p]]]<sdom[key[p]])
key[p] = key[ufs[p]];
return ufs[p] = temp;
}
void Sech2(LL u)
{
LL i, v;
val[u] += u;
for(i=0;i<Z[u].size();i++)
{
v = Z[u][i];
val[v] += val[u];
Sech2(v);
}
}
void Sech(LL p)
{
LL i, v;
dfn[p] = sdom[p] = ++cnt;
rak[cnt] = p;
for(i=0;i<G[p].size();i++)
{
v = G[p][i];
if(dfn[v]==0)
{
Sech(v);
fa[v] = p;
}
}
}
int main(void)
{
LL m, i, x, y, p, j, v;
while(scanf("%lld%lld", &n, &m)!=EOF)
{
cnt = 0;
for(i=1;i<=n;i++)
{
dfn[i] = val[i] = idom[i] = sdom[i] = 0;
ufs[i] = key[i] = i;
G[i].clear();
Gp[i].clear();
Z[i].clear();
}
for(i=1;i<=m;i++)
{
scanf("%lld%lld", &x, &y);
G[x].push_back(y);
Gp[y].push_back(x);
}
Sech(n);
for(i=cnt;i>=2;i--)
{
p = rak[i];
for(j=0;j<Gp[p].size();j++)
{
v = Gp[p][j];
if(dfn[v])
{
Find(v);
sdom[p] = min(sdom[p], sdom[key[v]]);
}
}
ufs[p] = fa[p];
Sp[rak[sdom[p]]].push_back(p);
for(j=0;j<Sp[fa[p]].size();j++)
{
v = Sp[fa[p]][j];
Find(v);
if(sdom[key[v]]==sdom[v])
idom[v] = fa[p];
else
idom[v] = key[v];
}
Sp[fa[p]].clear();
}
for(i=1;i<=cnt;i++)
{
p = rak[i];
if(idom[p]!=rak[sdom[p]])
idom[p] = idom[idom[p]];
}
for(i=1;i<=n-1;i++)
Z[idom[i]].push_back(i);
Sech2(n);
printf("%lld", val[1]);
for(i=2;i<=n;i++)
printf(" %lld", val[i]);
printf("\n");
}
return 0;
}
/*
13 21
13 2 11 12 7 4
2 3 12 1 6 4
3 4 13 11
4 5 8 12
2 6 1 10
6 7 10 9
13 8 10 5
8 9 5 13
9 10 5 4
8 11
*/