Description
There are N clones of Misaka Mikoto (sisters) forming the Misaka network. Some pairs of sisters are connected so that one of them can pass message to the other one. The sister with serial number N is the source of all messages. All the other sisters get message directly or indirectly from her. There might be more than one path from sister #N to sister #I, but some sisters do appear in all of these paths. These sisters are called important sister of sister #K. What are the important sisters of each sister?

Input
There are multiple test cases. Process to the End of File.
The first line of each test case contains two integers: the number of sisters 1 ≤ N ≤ 50,000 and the number of connections 0 ≤ M ≤ 100,000. The following M lines are M connections 1 ≤ Ai, Bi ≤ N, indicating that Ai can pass message to Bi.
Output
For each test case, output the sum of the serial numbers of important sisters of each sister, separated with single space.
Sample Input
3 2
3 2
2 1
5 7
3 2
1 2
2 1
3 1
3 2
5 3
5 4
Sample Output
6 5 3
9 10 8 9 5
题意:
给一张n个点m条边的有向图,求n号节点到每个点的必经点的编号之和。
题解:
支配树。
求出每个点的支配点之后,从dfn编号小的递推至大的
代码:
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
inline void W(long long x){
static int buf[50];
if(!x){putchar('0');return;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0])putchar(buf[buf[0]--]+'0');
}
const int N=1e5+50,M=4e5+50;
int n,m;
struct Graph{
int dfn[N],g[N],fa[N],id[N],v[M],nt[M],ec,tot;
int sdom[N],idom[N],mnsd[N],anc[N];long long sum[N];
vector<int>pre[N],buc[N];
inline void getanc(int p){
if(anc[p]!=p)getanc(anc[p]);
if(dfn[sdom[mnsd[anc[p]]]]<dfn[sdom[mnsd[p]]])mnsd[p]=mnsd[anc[p]];
anc[p]=anc[anc[p]];
}
inline int eval(int p){
getanc(p);
return mnsd[p];
}
inline void clear(){
memset(dfn,0,sizeof(dfn));
memset(g,0,sizeof(g));
memset(anc,0,sizeof(anc));
memset(sum,0,sizeof(sum));
ec=0;tot=0;
}
inline void add(int x,int y){nt[++ec]=g[x];g[x]=ec;v[ec]=y;}
inline void dfs(int now,int f=0){
fa[now]=f;dfn[now]=++tot;id[tot]=now;
sdom[now]=idom[now]=mnsd[now]=anc[now]=now;
for(int j=g[now];j;j=nt[j]){
if(dfn[v[j]])continue;
dfs(v[j],now);
}
}
inline void solve(){
for(int i=1;i<=n;i++)pre[i].clear(),buc[i].clear();
for(int i=1;i<=m;i++){
int x=rd(),y=rd();
add(x,y);
pre[y].push_back(x);
}
dfs(n,0);
for(int i=tot;i>=2;i--){
int u=id[i];
for(int j=pre[u].size()-1;j>=0;j--){
int t=eval(pre[u][j]);if(!dfn[t])continue;
if(dfn[sdom[u]]>dfn[sdom[t]])sdom[u]=sdom[t];
}
int f=fa[u];
anc[u]=f;
buc[sdom[u]].push_back(u);
for(int j=buc[f].size()-1;j>=0;j--){
int v=buc[f][j],t=eval(v);
if(dfn[sdom[t]]<dfn[sdom[v]])idom[v]=t;
else idom[v]=sdom[v];
}
buc[f].clear();
}
for(int i=2;i<=tot;i++)
if(idom[id[i]]!=sdom[id[i]])idom[id[i]]=idom[idom[id[i]]];
sum[id[1]]=id[1];
for(int i=2;i<=tot;i++)
sum[id[i]]=sum[idom[id[i]]]+id[i];
for(int i=1;i<n;i++)W((dfn[i]?sum[i]:0)),putchar(' ');
W((dfn[n]?sum[n]:0));
putchar('\n');
}
}g;
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
g.solve();
g.clear();
}
}
博客探讨了在包含多个克隆体Misaka Mikoto(姐妹)的Misaka网络中,信息传递路径的问题。妹妹编号为N的个体作为消息源,其他所有妹妹直接或间接接收她的消息。重要姐妹是指在所有从N到其他妹妹的路径中都出现的妹妹。博客提供了多组测试案例,展示了如何计算每个妹妹的重要姐妹编号之和,并给出了基于支配树的解决方案和实现代码。
776

被折叠的 条评论
为什么被折叠?



