ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

loj3504.「联合省选 2021 A」支配

2021-08-17 21:35:34  阅读:229  来源: 互联网

标签:10 支配 fa 省选 domain int 2021 loj3504 include


题目链接

看到题目名称,我反手就是一个支配树,很快啊……哦我不会支配树啊,那没事了。

看一眼数据范围……\(n\) 只有 \(3\times10^3\)?那直接 \(O(n^2)\) 枚举删掉每个点大力求出支配集合就好了。

然后根据支配集合的大小关系建出支配树来。

考虑新加入一条边 \((x,y)\),会有哪些点 \(i\) 在支配树上的父亲发生变化,手玩可以发现充要条件是:

  • \(x\) 不是 \(fa_i\);

  • \(fa_i\) 不是 \(1\);

  • 从 \(1\) 走到 \(x\) 不必须经过 \(fa_i\),即 \(fa_i\) 不支配 \(x\);

  • 从 \(y\) 走到 \(i\) 不必须经过 \(fa_i\)。

前三个条件在求支配树的时候都已经求出来了,最后一个条件建出反图,然后从每个 \(i\) 出发,钦定不能走 \(fa_i\),看看哪些点能到就好了,也能在 \(O(n^2)\) 的时间内与处理出来。

这样我们得出了哪些点的 \(fa_i\) 发生了改变,又因为树上的支配关系改变是具有传递性的,然后再线性推一遍标记就好了,时间复杂度 \(O(n(n+q))\)。

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
struct edge
{
    int nxt,to;
}e[6001<<1];
int n,m,q,tot,h[3001],fa[3001],id[3001],ans;
bool vis[3001][3001][2],tag[3001];
vector<int> domain[3001];
inline int read()
{
    int x=0;
    char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    while(c>='0'&&c<='9')
    {
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}
void print(int x)
{
    if(x>=10)
        print(x/10);
    putchar(x%10+'0');
}
inline bool cmp(int x,int y)
{
    return domain[x].size()<domain[y].size();
}
inline void add(int x,int y)
{
    e[++tot].nxt=h[x];
    h[x]=tot;
    e[tot].to=y;
}
void dfs1(int k,int ban)
{
    if(k==ban)
        return;
    vis[k][ban][0]=1;
    for(register int i=h[k];i;i=e[i].nxt)
        if(i&1)
            if(!vis[e[i].to][ban][0])
                dfs1(e[i].to,ban);
}
void dfs2(int k,int s,int ban)
{
    if(k==ban)
        return;
    vis[k][s][1]=1;
    for(register int i=h[k];i;i=e[i].nxt)
        if(!(i&1))
            if(!vis[e[i].to][s][1])
                dfs2(e[i].to,s,ban);
}
int main()
{
    n=read(),m=read(),q=read();
    for(register int i=1;i<=m;++i)
    {
        int x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    dfs1(1,0);
    for(register int i=1;i<=n;++i)
    {
        dfs1(1,i);
        for(register int j=1;j<=n;++j)
            if(vis[j][0][0]&&!vis[j][i][0])
                domain[j].push_back(i);
    }
    /*for(register int i=1;i<=n;++i,puts(""))
        for(register int j=0;j<(int)domain[i].size();++j)
            printf("%d ",domain[i][j]);*/
    for(register int i=1;i<=n;++i)
        id[i]=i;
    sort(id+1,id+n+1,cmp);
    for(register int i=2;i<=n;++i)
        for(register int j=0;j<(int)domain[i].size();++j)
            if(domain[domain[i][j]].size()==domain[i].size()-1)
            {
                fa[i]=domain[i][j];
                break;
            }
    for(register int i=2;i<=n;++i)
        dfs2(i,i,fa[i]);
    while(q--)
    {
        ans=0;
        int x=read(),y=read();
        for(register int i=1;i<=n;++i)
            if(fa[i]!=1&&x!=fa[i]&&vis[x][fa[i]][0]&&vis[y][i][1])
                tag[i]=1;
            else
                tag[i]=0;
        for(register int i=1;i<=n;++i)
            ans+=(tag[id[i]]|=tag[fa[id[i]]]);
        print(ans);
        putchar('\n');
    }
    return 0;
}

标签:10,支配,fa,省选,domain,int,2021,loj3504,include
来源: https://www.cnblogs.com/Forza-Ferrari/p/15154267.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有