# hdu 4695 Important Sisters

$$sdom(u) = min\{\{v|(v, u) \in E, dfn(v) < dfn(u)\}\cup\{sdom(q)|dfn(q)>dfn(u), \exists (p, x) \in E, q \in path(S, p)\}\}$$

$$idom(u) = \begin{cases}sdom(u)& \text{ if } sdom(v)= sdom(u)\\ idom(v) & \text{ if } sdom(v)<sdom(u) \end{cases}$$

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 200000;
int n, m;
int dfn[N], lst[N], id[N], sd[N], paid[N], mns[N];
int anc[N], par[N], tot;
vector <int> bi[N], bp[N], bb[N];
LL sum[N];
void dfs(int t)
{
dfn[t] = ++ tot; lst[tot] = t;
for (int i = 0; i < bi[t].size(); ++ i)
if (!dfn[bi[t][i]])
dfs(bi[t][i]), par[bi[t][i]] = t;
}
int check_min(int a, int b)
{
if (dfn[a] < dfn[b]) return a; else return b;
}
int find_anc(int t)
{
if (anc[t] == t) return t;
else
{
int a = find_anc(anc[t]);
if (a != anc[t] && dfn[sd[mns[anc[t]]]] < dfn[sd[mns[t]]])
mns[t] = mns[anc[t]];
return anc[t] = a;
}
}
int main()
{
while (scanf("%d%d", &n, &m) == 2)
{
for (int i = 0; i <= n; ++ i)
bi[i].clear(), bp[i].clear(), bb[i].clear();
for (int i = 0; i <= n; ++ i)
dfn[i] = lst[i] = par[i] = id[i] = sd[i] = paid[i] = sum[i] = 0;
for (int i = 1; i <= n; ++ i) anc[i] = mns[i] = i;
tot = 0;
for (int i = 1; i <= m; ++ i)
{
int a, b;
scanf("%d%d", &a, &b);
bi[a].push_back(b);
bp[b].push_back(a);
}
dfs(n);
for (int i = n; ; -- i)
{
for (int j = 0; j < bb[lst[i]].size(); ++ j)
{
find_anc(bb[lst[i]][j]);
if (sd[mns[bb[lst[i]][j]]] == sd[bb[lst[i]][j]])
id[bb[lst[i]][j]] = sd[bb[lst[i]][j]];
else
paid[bb[lst[i]][j]] = mns[bb[lst[i]][j]];
}
if (i == 1) break;
sd[lst[i]] = par[lst[i]];
for (int j = 0; j < bp[lst[i]].size(); ++ j) if (dfn[bp[lst[i]][j]])
{
if (dfn[bp[lst[i]][j]] < i)
sd[lst[i]] = check_min(sd[lst[i]], bp[lst[i]][j]);
else
{
find_anc(bp[lst[i]][j]);
sd[lst[i]] = check_min(sd[lst[i]], sd[mns[bp[lst[i]][j]]]);
}
}
mns[lst[i]] = lst[i];
anc[lst[i]] = par[lst[i]];
bb[sd[lst[i]]].push_back(lst[i]);
}
for (int i = 1; i <= n; ++ i) if (paid[lst[i]])
id[lst[i]] = id[paid[lst[i]]];
// for (int i = 1; i <= n; ++ i)
// printf("%d\n", id[i]);
for (int i = 1; i <= n; ++ i)
sum[lst[i]] = sum[id[lst[i]]] + lst[i];
for (int i = 1; i <= n; ++ i)
printf("%lld%c", sum[i], (i == n? '\n': ' '));
}
}

posted @ 2017-12-24 21:33  AwD!  阅读(298)  评论(0编辑  收藏