有N个妹妹,然后从N号妹妹开始发消息,现在每个妹妹都想知道消息是什么,但是消息只有M条有向路径来传播,然后现在询问每个点u,从N号妹妹到她的路径上有哪些必经点,将这些必经点的点序号求和后输出。
所以,这就是一个一般图上的Dominator Tree问题,一般图的支配树问题,直接建支配树,然后求一个“深度”即可。然后因为是多组输入,记得初始化。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #include <bitset> #include <unordered_map> #include <unordered_set> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define HalF (l + r)>>1 #define lsn rt<<1 #define rsn rt<<1|1 #define Lson lsn, l, mid #define Rson rsn, mid+1, r #define QL Lson, ql, qr #define QR Rson, ql, qr #define myself rt, l, r #define pii pair<int, int> #define MP(a, b) make_pair(a, b) using namespace std; typedef unsigned long long ull; typedef unsigned int uit; typedef long long ll; const int maxN = 5e4 + 7, maxM = 2e5 + 7; int N, M; namespace Graph { int head[maxN], cnt; struct Eddge { int nex, to; Eddge(int a=-1, int b=0):nex(a), to(b) {} } edge[maxM]; inline void addEddge(int u, int v) { edge[cnt] = Eddge(head[u], v); head[u] = cnt++; } inline void init() { cnt = 0; for(int i=1; i<=N; i++) head[i] = -1; } }; using namespace Graph; namespace Dominator { int tim; int dfn[maxN], rid[maxN], fa[maxN], sdom[maxN], idom[maxN]; int fo[maxN], vo[maxN]; vector<int> pre[maxN], bkt[maxN]; int findf(int p) { if(fo[p]==p) return p; int r = findf(fo[p]); if(sdom[vo[fo[p]]]<sdom[vo[p]]) vo[p] = vo[fo[p]]; return fo[p] = r; } inline int eval(int p) { findf(p); return vo[p]; } void dfs(int p) { rid[dfn[p]=++tim] = p; sdom[p] = dfn[p]; for(int i=head[p]; ~i; i=edge[i].nex) if(!dfn[edge[i].to]) { dfs(edge[i].to); fa[edge[i].to] = p; } } void work() { int p; dfs(N); for(int i=tim; i>=2; i--) { p = rid[i]; for(int k : pre[p]) if(dfn[k]) sdom[p] = min(sdom[p], sdom[eval(k)]); bkt[rid[sdom[p]]].push_back(p); int fp = fa[p]; fo[p] = fa[p]; for(int v : bkt[fp]) { int u = eval(v); idom[v] = sdom[u] == sdom[v] ? fp : u; } bkt[fp].clear(); } for(int i=2; i<=tim; i++) { p = rid[i]; idom[p] = idom[p] == rid[sdom[p]] ? idom[p] : idom[idom[p]]; } for(int i=2; i<=tim; i++) { p = rid[i]; sdom[p] = rid[sdom[p]]; } } inline void link(int a, int b) { addEddge(a, b); pre[b].push_back(a); } void init() { tim = 0; for(int i=1; i<=N; i++) { dfn[i] = idom[i] = 0; fo[i] = vo[i] = i; pre[i].clear(); bkt[i].clear(); } } }; using namespace Dominator; vector<int> E[maxN]; ll siz[maxN]; void last_dfs(int u) { siz[u] += u; for(int v : E[u]) { siz[v] = siz[u]; last_dfs(v); } } int main() { while(scanf("%d%d", &N, &M) != EOF) { Graph::init(); Dominator::init(); for(int i=1, u, v; i<=M; i++) { scanf("%d%d", &u, &v); link(u, v); } work(); for(int i=1; i<=N; i++) { E[i].clear(); siz[i] = 0; } for(int i=1; i<N; i++) E[idom[i]].push_back(i); siz[N] = 0; last_dfs(N); for(int i=1; i<=N; i++) printf("%lld%c", siz[i], i == N ? '\n' : ' '); } return 0; }