题意:n个顶点编号为1到n,求从第n个顶点到其他每个顶点中所必须经过的所有顶点编号之和。
构造支配树求答案即可。
感觉对我这种菜鸡来说用处不大… 学一下模板吧
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define ll long long
const int maxn = 50010;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to, next;
} edge[100010 * 2];
int head[maxn], _head[maxn], tot;
void Add(int head[], int x, int y)
{
edge[++tot].to = y;
edge[tot].next = head[x];
head[x] = tot;
}
int n, m;
ll ans[maxn];
int fa[maxn], dfn[maxn], idx[maxn], semi[maxn], idom[maxn], T;
vector <int> dom[maxn];
bool Compare(int x, int y)
{
return dfn[semi[x]] < dfn[semi[y]];
}
int father[maxn], best[maxn];
void init()
{
for (int i = 1; i <= n; i++)
father[i] = best[i] = i;
}
int Find(int x)
{
if (father[x] == x) return x;
int p = Find(father[x]);
best[x] = min(best[x], best[father[x]], Compare);
return father[x] = p;
}
void Initialize()
{
tot = 0;
T = 0;
init();
memset(head, 0, sizeof(head));
memset(_head, 0, sizeof(_head));
memset(ans, 0, sizeof(ans));
memset(fa, 0, sizeof(fa));
memset(dfn, 0, sizeof(dfn));
memset(idx, 0, sizeof(idx));
memset(semi, 0, sizeof(semi));
memset(idom, 0, sizeof(idom));
}
void DFS(int x)
{
idx[dfn[x] = ++T] = x;
for (int i = head[x]; i; i = edge[i].next)
if (!dfn[edge[i].to])
DFS(edge[i].to), fa[edge[i].to] = x;
}
void Lengauer_Tarjan()
{
DFS(n);
dfn[0] = INF;
for (int j = T; j; j--)
{
int x = idx[j];
if (j != 1)
{
for (int i = _head[x]; i; i = edge[i].next)
{
if (!dfn[edge[i].to]) continue;
if (dfn[edge[i].to] > dfn[x])
{
Find(edge[i].to);
if (dfn[semi[best[edge[i].to]]] < dfn[semi[x]])
semi[x] = semi[best[edge[i].to]];
}
else
{
if (dfn[edge[i].to] < dfn[semi[x]])
semi[x] = edge[i].to;
}
}
dom[semi[x]].push_back(x);
}
while (dom[x].size())
{
int y = dom[x].back();
dom[x].pop_back();
Find(y);
if (semi[best[y]] != x)
idom[y] = best[y];
else idom[y] = x;
}
for (int i = head[x]; i; i = edge[i].next)
if (fa[edge[i].to] == x)
father[edge[i].to] = x;
}
for (int j = 2; j <= T; j++)
{
int x = idx[j];
if (idom[x] != semi[x]) idom[x] = idom[idom[x]];
}
idom[idx[1]] = 0;
}
ll Get_Ans(int x)
{
if (x == n) return ans[x] = n;
if (ans[x]) return ans[x];
return ans[x] = Get_Ans(idom[x]) + x;
}
int main()
{
while (scanf("%d %d", &n, &m) != EOF)
{
Initialize();
int x, y;
for (int i = 1; i <= m; i++)
{
scanf("%d %d", &x, &y);
Add(head, x, y);
Add(_head, y, x);
}
Lengauer_Tarjan();
for (int i = 1; i <= n; i++)
{
if (dfn[i]) cout << Get_Ans(i);
else printf("0");
if (i == n) putchar('\n');
else putchar(' ');
}
}
return 0;
}