P5180 【模板】支配树
这个题乱七八糟的,和之前的灭绝树有点像,但是不一样。那个是DAG,这个是有向图。简单步骤就是先求出来dfs序,然后求出半支配点(?),然后通过这个求支配点。
算法不是很理解,先放在这。
题干:
题目背景
模板题,无背景
题目描述
给定一张有向图,求从1号点出发,每个点能支配的点的个数(包括自己)
输入输出格式
输入格式:
第一行两个正整数n,mn,mn,m,表示点数和边数 接下来mmm行,每行输入两个整数u,vu,vu,v,表示有一条uuu到vvv的有向边
输出格式:
一行输出nnn个整数,表示每个点能支配的点的个数
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(register int i = a;i <= n;++i) #define lv(i,a,n) for(register int i = a;i >= n;--i) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 1e6 + 5; int dfn[N],n,m; struct node { int l,r,nxt; }a[N << 1],b[N << 1],c[N << 1]; int len = 0,len1 = 0,lst[N],pre[N],len2 = 0,lat[N]; void add(int x,int y) { a[++len].l = x; a[len].r = y; a[len].nxt = lst[x]; lst[x] = len; } void dda(int x,int y) { b[++len1].l = x; b[len1].r = y; b[len1].nxt = pre[x]; pre[x] = len1; } void add1(int x,int y) { c[++len2].l = x; c[len2].r = y; c[len2].nxt = lat[x]; lat[x] = len2; } int sdom[N],bel[N],id[N],val[N],cnt = 0; int fa[N],tot = 0,idom[N]; void dfs(int now) { dfn[now] = ++cnt; id[cnt] = now; for(int k = lst[now];k;k = a[k].nxt) { int y = a[k].r; if(dfn[y]) continue; dfs(y); fa[y] = now; } } int find(int x) { if(x == bel[x]) return x; int root = find(bel[x]); if(dfn[sdom[val[bel[x]]]] < dfn[sdom[val[x]]]) val[x] = val[bel[x]]; return bel[x] = root; } /*int find(int x) { if(x==bel[x]) return x; int root=find(bel[x]); if(dfn[sdom[val[bel[x]]]]<dfn[sdom[val[x]]]) val[x]=val[bel[x]]; return bel[x]=root; }*/ void tarjan() { for(int i = cnt;i >= 2;i--) { int now = id[i]; for(int k = pre[now];k;k = b[k].nxt) { int y = b[k].r; if(!dfn[y]) continue; find(y); if(dfn[sdom[val[y]]] < dfn[sdom[now]]) sdom[now] = sdom[val[y]]; } add1(sdom[now],now); bel[now] = fa[now]; now = fa[now]; for(int k = lat[now];k;k = c[k].nxt) { int v = c[k].r; find(v); if(sdom[val[v]] == now) idom[v] = now; else idom[v] = val[v]; } } for(int i = 2,now;i <= cnt;i++) { now = id[i]; if(idom[now] != sdom[now]) idom[now] = idom[idom[now]]; } } int ans[N]; void dfs_ans(int now) { ans[now] = 1; for(int k = lst[now];k;k = a[k].nxt) { int y = a[k].r; dfs_ans(y); ans[now] += ans[y]; } } int main() { read(n);read(m); duke(i,1,m) { int x,y; read(x);read(y); add(x,y);dda(y,x); } duke(i,1,n) { sdom[i] = bel[i] = val[i] = i; } dfs(1); tarjan(); len = 0; clean(lst); for(int i = 2;i <= n;i++) if(idom[i]) add(idom[i],i); dfs_ans(1); duke(i,1,n) { printf("%d ",ans[i]); } return 0; }
只想找一个不会伤害我的人