题目大意:给定一张
n
个点
数据是错的,存在
n
号点无法到达的点,这些点输出0
求Dominator Tree的Lengauer-Tarjan算法,具体做法自己百度我不赘述了
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 50500
using namespace std;
inline void Assert(bool flag)
{
if(!flag) while(1) puts("233");
//if(!flag) throw false;
}
struct abcd{
int to,next;
}table[100100<<1];
int head[M],_head[M],tot;
void Add(int head[],int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
int n,m;
long long ans[M];
int fa[M],dfn[M],identification[M],semi[M],idom[M],T;
vector<int> dom[M];
bool Compare(int x,int y)
{
return dfn[semi[x]] < dfn[semi[y]] ;
}
namespace Union_Find_Set{
int fa[M],best[M];
void Initialize()
{
int i;
for(i=1;i<=n;i++)
fa[i]=best[i]=i;
}
int Find(int x)
{
if(fa[x]==x)
return x;
int p=Find(fa[x]);
best[x]=min(best[x],best[fa[x]],Compare);
return fa[x]=p;
}
}
void Initialize()
{
memset(head,0,sizeof head);
memset(_head,0,sizeof _head);tot=0;
memset(ans,0,sizeof ans);
memset(fa,0,sizeof fa);
memset(dfn,0,sizeof dfn);T=0;
memset(identification,0,sizeof identification);
memset(semi,0,sizeof semi);
memset(idom,0,sizeof idom);
Union_Find_Set::Initialize();
}
void DFS(int x)
{
int i;
identification[dfn[x]=++T]=x;
for(i=head[x];i;i=table[i].next)
if(!dfn[table[i].to])
DFS(table[i].to),fa[table[i].to]=x;
}
void Lengauer_Tarjan()
{
int i,j;
DFS(n);
dfn[0]=0x3f3f3f3f;
//Assert(T==n);
for(j=T;j;j--)
{
int x=identification[j];
if(j!=1)
{
for(i=_head[x];i;i=table[i].next)
{
if(!dfn[table[i].to]) continue;
if(dfn[table[i].to]>dfn[x])
{
Union_Find_Set::Find(table[i].to);
if(dfn[semi[Union_Find_Set::best[table[i].to]]]<dfn[semi[x]])
semi[x]=semi[Union_Find_Set::best[table[i].to]];
}
else
{
if(dfn[table[i].to]<dfn[semi[x]])
semi[x]=table[i].to;
}
}
dom[semi[x]].push_back(x);
}
while(dom[x].size())
{
int y=dom[x].back();
dom[x].pop_back();
Union_Find_Set::Find(y);
if(semi[Union_Find_Set::best[y]]!=x)
idom[y]=Union_Find_Set::best[y];
else
idom[y]=x;
}
for(i=head[x];i;i=table[i].next)
if(fa[table[i].to]==x)
Union_Find_Set::fa[table[i].to]=x;
}
for(j=2;j<=T;j++)
{
int x=identification[j];
if(idom[x]!=semi[x])
idom[x]=idom[idom[x]];
}
idom[identification[1]]=0;
}
long long Get_Ans(int x)
{
//Assert(x);
if(x==n) return ans[x]=n;
if(ans[x]) return ans[x];
return ans[x]=Get_Ans(idom[x])+x;
}
int main()
{
#ifdef PoPoQQQ
freopen("4694.in","r",stdin);
freopen("4694.out","w",stdout);
#endif
int i,x,y;
while(scanf("%d%d",&n,&m)!=EOF)
{
Initialize();
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
Add(head,x,y);
Add(_head,y,x);
}
Lengauer_Tarjan();
for(i=1;i<=n;i++)
printf("%I64d%c",dfn[i]?Get_Ans(i):0,i==n?'\n':' ');
}
return 0;
}