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;
}

猜你喜欢

转载自www.cnblogs.com/DukeLv/p/10424735.html