P7520-[省选联考 2021 A 卷]支配
正題
題目鏈接:https://www.luogu.com.cn/problem/P7520
題目大意
給出nnn個(gè)點(diǎn)mmm條邊的一張有向圖,一號(hào)點(diǎn)為起始點(diǎn),qqq次獨(dú)立的詢問加入一條邊后有多少個(gè)點(diǎn)的支配集發(fā)生了變化。
1≤n≤3000,1≤m≤2×n,1≤q≤2×1041\leq n\leq 3000,1\leq m\leq 2\times n,1\leq q\leq 2\times 10^41≤n≤3000,1≤m≤2×n,1≤q≤2×104
解題思路
首先我們肯定是先建一棵支配樹,可以直接O(n2)O(n^2)O(n2)搞。
具體的做法我是從1~n1\sim n1~n枚舉,然后枚舉到xxx時(shí)把xxx刪掉從111開始遍歷,如果對(duì)于一個(gè)點(diǎn)yyy滿足yyy不能到達(dá)且fayfa_yfay?能夠到達(dá),那么fayfa_yfay?改為xxx即可。
然后考慮一條邊x→yx\rightarrow yx→y能改變支配集的話,防止麻煩我們對(duì)于每個(gè)點(diǎn)xxx只考慮它的父節(jié)點(diǎn)faxfa_xfax?,如果1~y1\sim y1~y存在一個(gè)點(diǎn)xxx使得faxfa_xfax?不再支配xxx,那么yyy的支配集肯定改變。
那么考慮對(duì)于一個(gè)邊x→yx\rightarrow yx→y,如果存在一條路徑1→x→y→i1\rightarrow x\rightarrow y\rightarrow i1→x→y→i且不經(jīng)過iii的父節(jié)點(diǎn),那么iii整個(gè)子樹的支配集都會(huì)改變,首先條件是1→x1\rightarrow x1→x不經(jīng)過faifa_ifai?,這個(gè)很簡單,如果xxx不在faifa_ifai?的子樹內(nèi)就好了。然后是y→iy\rightarrow iy→i這個(gè)條件,也很好搞,枚舉點(diǎn)iii,把faifa_ifai?刪去,然后看iii走反圖能到達(dá)的點(diǎn),這些點(diǎn)都可以作為yyy,提前O(n2)O(n^2)O(n2)預(yù)處理就好了。
然后詢問的時(shí)候我們暴力枚舉所有點(diǎn)判斷是否合法,然后樹上差分來統(tǒng)計(jì)答案就好了。
時(shí)間復(fù)雜度:O(n2+nq)O(n^2+nq)O(n2+nq)
code
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N=3010; int n,m,q,cnt,ans,fa[N],v[N],rfn[N],ed[N]; vector<int> F[N],G[N],T[N]; bool f[N][N]; void dfs(int x){if(v[x])return;v[x]=1;for(int i=0;i<G[x].size();i++)dfs(G[x][i]);return; } void dfs2(int x){rfn[x]=++cnt;for(int i=0;i<T[x].size();i++)dfs2(T[x][i]);ed[x]=cnt;return; } void dfs3(int x){if(v[x])return;v[x]=1;for(int i=0;i<F[x].size();i++)dfs3(F[x][i]);return; } void dfs4(int x,int w){w|=v[x];ans+=w;for(int i=0;i<T[x].size();i++)dfs4(T[x][i],w);return; } int main() {scanf("%d%d%d",&n,&m,&q);for(int i=1,x,y;i<=m;i++){scanf("%d%d",&x,&y);G[x].push_back(y);F[y].push_back(x);}for(int i=1;i<=n;i++){memset(v,0,sizeof(v));v[i]=2;dfs(1);v[0]=1;for(int j=1;j<=n;j++)if(!v[j]&&v[fa[j]])fa[j]=i;}for(int i=2;i<=n;i++)T[fa[i]].push_back(i);dfs2(1);for(int i=2;i<=n;i++){memset(v,0,sizeof(v));v[fa[i]]=2;dfs3(i);for(int j=1;j<=n;j++)if(v[j]==1)f[j][i]=1;}while(q--){int x,y;ans=0;memset(v,0,sizeof(v));scanf("%d%d",&x,&y);for(int i=1;i<=n;i++){if(!f[y][i])continue;if(rfn[fa[i]]<=rfn[x]&&ed[fa[i]]>=rfn[x])continue;v[i]=1;}dfs4(1,0);printf("%d\n",ans);}return 0; }總結(jié)
以上是生活随笔為你收集整理的P7520-[省选联考 2021 A 卷]支配的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国邮政快递收费是如何收费的
- 下一篇: 另一个博客