题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=
题意:
给你n个女生的联系情况,第n个人是大姐大(即题目中的根),从它开始会向其他人发送消息,如果第y个人失联了那么第x个人就无法收到消息,就称y是x的一个重要的姐妹,现在问你每个人的重要的姐妹的编号总和,如果不连通那么就是0。
做法:
看了将近三个小时的支配树,总算是明白了一点点了。
https://blog.csdn.net/litble/article/details/83019578 感觉别人讲的会比较透一点 感性理解叭 自己也加了点备注。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
using namespace std;
typedef long long ll;
const int maxn=50005;
const int maxm=100005;
int to[maxm],nex[maxm],head[maxn],cnt;
int n,m,dfn[maxn],fa[maxn],tot,Sfa[maxn];
int idom[maxn],semi[maxn],id[maxn],val[maxn];
vector<int> pre[maxn],dom[maxn];
void add(int u,int v){
to[cnt]=v,nex[cnt]=head[u];
head[u]=cnt++;
}
int fin(int x){
if(Sfa[x]==x) return x;
int tmp=fin(Sfa[x]);
if(dfn[semi[val[Sfa[x]]]]<dfn[semi[val[x]]]) val[x]=val[Sfa[x]];
return Sfa[x]=tmp;
}
void dfs(int u){
dfn[u]=++tot; id[tot]=u;
for(int i=head[u];~i;i=nex[i]){
int v=to[i];
pre[v].push_back(u);
//把所有和这个点相连的点都加入了pre里
if(!dfn[v]){
fa[v]=u;
dfs(v);
}
}
}
int smin(int x,int y){
return dfn[x]<dfn[y]?x:y;
}
void solve(){
for(int i=tot;i>=2;i--){
int u=id[i];
if(!pre[u].empty()){
for(int j=0;j<pre[u].size();j++){
int v=pre[u][j];
//如果< 则表示为祖先 找小的就好了
if(dfn[v]<dfn[u]) semi[u]=smin(semi[u],v);
else{
//否则则是后代 先进行后代中最小dfn的semi更新
//用并查集来进行维护 再看哪个semi小来决定是否更新
fin(v);
semi[u]=smin(semi[u],semi[val[v]]);
}
}
}
Sfa[u]=fa[u]; dom[semi[u]].push_back(u);
if(!dom[fa[u]].empty()){
for(int j=0;j<dom[fa[u]].size();j++){
int v=dom[fa[u]][j]; fin(v);
int aim=val[v];
idom[v]=(dfn[semi[aim]]<dfn[semi[v]])?aim:fa[u];
}
}
}
for(int i=2;i<=tot;i++){
int x=id[i];
if(idom[x]!=semi[x]) idom[x]=idom[idom[x]];
}
}
ll ans[maxn];
void Cal(){
rep(i,1,n) ans[i]=0;
rep(i,1,tot){
int x=id[i];
ans[x]+=x;
if(idom[x]) ans[x]+=ans[idom[x]];
}
}
int main(){
while(~scanf("%d%d",&n,&m)){
rep(i,1,n){
head[i]=-1; Sfa[i]=val[i]=semi[i]=i;
dfn[i]=idom[i]=0;
pre[i].clear(); dom[i].clear();
}
cnt=0; tot=0;
rep(i,1,m){
int x,y; scanf("%d%d",&x,&y);
add(x,y);
}
dfs(n);
solve();
Cal();
for(int i=1;i<=n;i++){
if(i!=1) printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}