支配树模板
考试的时候sb $n^3$ 建了个支配树。明明 $n^2$ 是个人都能想出来。
这东西背个定理和模板就行了(反正我不会证)。
每次先求出dfs序,把semi[i]设成dfn[i].我的semi中存的dfs编号.
按dfs序从大到小求sdom,用并查集维护这每个点到当前根路径上semi最小的点,显然遍历一遍pre[i]就能求出semi[i].
把i放到semi[i]的vector里。
然后显然当前i这棵子树已经遍历完了,把fa[i]的vector中的元素提取出来算idom,清空vector.
最后dfs序从小到大把idom[x]!=id[semi[x]]的x改为idom[idom[x]]。
代码很丑。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<bitset> 6 #include<vector> 7 #define N 2000005 8 #define M 2000005 9 #define ll long long 10 using namespace std; 11 int n,k,m; 12 int head[N],ver[M],nxt[M],tot; 13 void add(int a,int b) 14 { 15 tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ; 16 } 17 int map[N]; 18 bool ok[N]; 19 int head2[N],ver2[M],nxt2[M],tot2; 20 void add2(int a,int b) 21 { 22 tot2++;nxt2[tot2]=head2[a];head2[a]=tot2;ver2[tot2]=b;return ; 23 } 24 bool v[N]; 25 int dfn[N],fa[N],z,id[N]; 26 int sdom[N],idom[N]; 27 // sdom dfs序 idom 真实编号 28 void dfs(int x,int now) 29 { 30 map[x]=1;dfn[x]=++z;id[z]=x;sdom[x]=z; 31 for(int i=head[x];i;i=nxt[i]) 32 { 33 if(!map[ver[i]]) 34 { 35 fa[ver[i]]=x; 36 dfs(ver[i],now); 37 } 38 } 39 return ; 40 } 41 int dom[N];int ban[N]; 42 bool dffs(int x,int pp) 43 { 44 v[x]=1; 45 for(int i=head[x];i;i=nxt[i]) 46 { 47 if(ban[ver[i]]||v[ver[i]])continue; 48 if(ver[i]==pp||dffs(ver[i],pp))return 1; 49 } 50 return 0; 51 } 52 int dep[N]; 53 bool pan(int x) 54 { 55 memset(v,0,sizeof(v)); 56 if(dffs(0,x))return 1; 57 return 0; 58 } 59 ll ans;int size[N]; 60 void dfs2(int x) 61 { 62 v[x]=1;size[x]=1; 63 for(int i=head2[x];i;i=nxt2[i]) 64 { 65 dep[ver2[i]]=dep[x]+1; 66 dfs2(ver2[i]); 67 size[x]+=size[ver2[i]]; 68 } 69 if(x!=0&&dep[x]==1)ans+=1LL*size[x]*(size[x]-1)/2; 70 return ; 71 } 72 vector<int>pre[N],sub[N]; 73 int f[N],va[N]; 74 int find(int x) 75 { 76 if(x==f[x])return x; 77 int nw=find(f[x]); 78 if(sdom[va[f[x]]]<sdom[va[x]])va[x]=va[f[x]]; 79 return f[x]=nw; 80 } 81 int eval(int x) 82 { 83 find(x); 84 return va[x]; 85 } 86 void solve() 87 { 88 for(int i=1;i<=n;i++)f[i]=i,va[i]=i; 89 for(int i=z;i>=2;i--) 90 { 91 int p=id[i]; 92 for(int j=0;j<pre[p].size();j++) 93 { 94 if(dfn[pre[p][j]])sdom[p]=min(sdom[p],sdom[eval(pre[p][j])]); 95 } 96 sub[id[sdom[p]]].push_back(p); 97 f[p]=fa[p]; 98 for(int j=0;j<sub[fa[p]].size();j++) 99 { 100 int tmp=sub[fa[p]][j]; 101 if(sdom[eval(tmp)]==sdom[tmp])idom[tmp]=fa[p]; 102 else idom[tmp]=eval(tmp); 103 } 104 sub[fa[p]].clear(); 105 } 106 int p; 107 for(int i=2;i<=z;i++) 108 { 109 p=id[i]; 110 if(idom[p]!=id[sdom[p]])idom[p]=idom[idom[p]]; 111 add2(idom[p],p); 112 } 113 return ; 114 } 115 int main() 116 { 117 scanf("%d%d",&n,&k); 118 for(int i=1;i<=k;i++) 119 { 120 int cnt,tmp;scanf("%d",&cnt); 121 for(int j=1;j<=cnt;j++) 122 { 123 scanf("%d",&tmp); 124 add(tmp,i); 125 pre[i].push_back(tmp); 126 } 127 } 128 for(int i=k+1;i<=n;i++)add(0,i),pre[i].push_back(0); 129 dfs(0,0); 130 int ans0=0; 131 for(int i=1;i<=k;i++) 132 { 133 if(map[i]) 134 { 135 ok[i]=1; 136 continue; 137 } 138 if(!ok[i])ans0++; 139 } 140 printf("%d\n",ans0); 141 for(int i=1;i<=k;i++) 142 { 143 if(!ok[i])printf("%d ",i); 144 }puts(""); 145 solve(); 146 memset(v,0,sizeof(v)); 147 dfs2(0); 148 printf("%lld\n",ans); 149 return 0; 150 }