https://www.luogu.org/problemnew/show/P4606
把原来的图的点双联通分量缩点(每个双联通分量建一个点,每个割点再建一个点)(用符合逻辑的方式)建一棵树(我最开始建的想法就有问题,答案竟然还差不多,查了好久才发现……然后重新想了个正确的建法发现比之前那个错误的建法好写多了,气),然后把这棵树整成虚树再做个树上dp就(安排得)明明白白的了。dp的时候注意一下树的根的值也要统计。
我的程序大概常数太大了洛谷开O2才能过,BZOJ会tle,也不想改了,就这样吧……
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 const int maxn=500010; 8 int n,m; 9 struct nod{ 10 int y,next; 11 };nod e1[maxn*8];nod e[maxn*8];nod e2[maxn*8]; 12 int head1[maxn]={},head[maxn]={},tot1=0,tot=0; 13 int head2[maxn]={},tot2=0; 14 int dfn[maxn]={},low[maxn]={},bel[maxn]={},bel1[maxn]={},poi[maxn]={},sta[maxn]={},tai,cnt,tn; 15 int val[maxn]={}; 16 int pa[maxn]={}; 17 void init1(int x,int y){ e1[++tot1].y=y;e1[tot1].next=head1[x];head1[x]=tot1; } 18 void init(int x,int y){ e[++tot].y=y;e[tot].next=head[x];head[x]=tot; } 19 void init2(int x,int y){ e2[++tot2].y=y;e2[tot2].next=head2[x];head2[x]=tot2; } 20 int getpa(int x){return x==pa[x]?x:getpa(pa[x]);} 21 void merpa(int x,int y){ 22 x=getpa(x);y=getpa(y); 23 pa[x]=pa[y]; 24 } 25 void Tarjan(int x,int p){ 26 dfn[x]=low[x]=++cnt;sta[++tai]=x; int z=0; 27 for(int i=head1[x];i;i=e1[i].next){ 28 if(e1[i].y==p)continue; 29 if(!dfn[e1[i].y]){ 30 Tarjan(e1[i].y,x); 31 low[x]=min(low[e1[i].y],low[x]); 32 if(low[e1[i].y]>=dfn[x]){ 33 int w; ++tn;++z; 34 if(low[e1[i].y]==dfn[x]&&!p)bel[x]=tn; 35 do{ 36 w=sta[tai--]; 37 bel[w]=tn; 38 }while(w!=e1[i].y); 39 } 40 } 41 else low[x]=min(low[x],dfn[e1[i].y]); 42 } 43 if(z>=1&&p){ 44 poi[x]=1; 45 bel1[x]=++tn; 46 } 47 if(!p){ 48 if(z>1){poi[x]=1;bel1[x]=++tn;} 49 if(!bel[x])bel[x]=++tn; 50 } 51 } 52 void dfs1(int x){ 53 for(int i=head1[x];i;i=e1[i].next){ 54 int y=e1[i].y; 55 if(poi[y]){ 56 if(getpa(bel1[y])!=getpa(bel[x])){ 57 init(bel1[y],bel[x]);init(bel[x],bel1[y]); 58 merpa(bel1[y],bel[x]); 59 } 60 } 61 } 62 } 63 void dfs11(int x){ 64 for(int i=head1[x];i;i=e1[i].next){ 65 int y=e1[i].y; 66 if(poi[y]){ 67 if(getpa(bel1[y])!=getpa(bel1[x])){ 68 init(bel1[y],bel1[x]);init(bel1[x],bel1[y]); 69 merpa(bel1[y],bel1[x]); 70 } 71 } 72 } 73 } 74 int dep[maxn]={},fa[maxn][30]={},id[maxn]={},shu; 75 int a[maxn]={},val1[maxn]; 76 void dfs(int x,int p){ 77 dep[x]=dep[p]+1;fa[x][0]=p;val[x]=val[p]+val1[x];id[x]=++shu; 78 //cout<<x<<shu<<endl; 79 for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1]; 80 for(int i=head[x];i;i=e[i].next){ 81 if(e[i].y==p)continue; 82 dfs(e[i].y,x); 83 } 84 } 85 bool mcmp(int x,int y){ 86 return id[x]<id[y]; 87 } 88 int getlca(int x,int y){ 89 if(dep[x]<dep[y])swap(x,y); 90 if(dep[x]!=dep[y])for(int i=20;i>=0;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; 91 if(x==y)return x; 92 for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];} 93 return fa[x][0]; 94 } 95 int dfs2(int x){ 96 int ans=0;//cout<<x<<endl; 97 for(int i=head2[x];i;i=e2[i].next){//cout<<x<<e2[i].y<<endl; 98 ans+=dfs2(e2[i].y); 99 ans+=val[e2[i].y]-val[x]; 100 } 101 return ans; 102 } 103 void dfs3(int x){ 104 for(int i=head2[x];i;i=e2[i].next){ 105 dfs3(e2[i].y); 106 }head2[x]=0; 107 } 108 void solve(){ 109 int nm;scanf("%d",&nm); 110 int tly=1,w=0; 111 for(int i=1;i<=nm;i++){ scanf("%d",&a[i]); if(poi[a[i]]){a[i]=bel1[a[i]]; }else a[i]=bel[a[i]];} 112 sort(a+1,a+1+nm,mcmp); 113 for(int i=2;i<=nm;i++)if(a[tly]!=a[i])a[++tly]=a[i]; 114 tot2=0;tai=1;sta[1]=a[1];w-=val1[a[1]]; 115 for(int i=2;i<=tly;i++){ 116 int lc=getlca(sta[tai],a[i]);w-=val1[a[i]];//cout<<a[i]<<sta[tai]<<lc<<endl; 117 while(tai&&dep[lc]<dep[sta[tai]]){ 118 if(tai==1||(tai>1&&dep[sta[tai-1]]<dep[lc])){ 119 init2(lc,sta[tai]);tai--;break; 120 } 121 if(tai-1>0)init2(sta[tai-1],sta[tai]); 122 tai--; 123 } 124 if(sta[tai]!=lc||!tai)sta[++tai]=lc; 125 if(sta[tai]!=a[i]||!tai)sta[++tai]=a[i]; 126 } 127 while(--tai){init2(sta[tai],sta[tai+1]);} 128 w+=dfs2(sta[1]); dfs3(sta[1]); 129 //cout<<tly<<' '<<a[1]<<' '<<a[2]<<endl; 130 //cout<<sta[1]<<' '<<getlca(a[1],a[2])<<endl; 131 w+=val1[sta[1]]; 132 cout<<w<<endl; 133 } 134 int main(){ 135 //freopen("game.in","r",stdin); 136 //freopen("game.out","w",stdout); 137 int T;scanf("%d",&T); 138 while(T-->0){ 139 scanf("%d%d",&n,&m); 140 memset(dfn,0,sizeof(dfn)); 141 memset(poi,0,sizeof(poi)); 142 memset(low,0,sizeof(low)); 143 memset(bel,0,sizeof(bel)); 144 memset(bel1,0,sizeof(bel1)); 145 memset(head1,0,sizeof(head1)); 146 memset(head2,0,sizeof(head2)); 147 memset(head,0,sizeof(head)); 148 memset(fa,0,sizeof(fa)); 149 memset(val,0,sizeof(val)); 150 memset(val1,0,sizeof(val1)); 151 tot1=0,tot2=0,tot=0;cnt=0;tn=0;tai=0;shu=0; 152 int x,y; 153 for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);if(x==y)continue;init1(x,y);init1(y,x);} 154 Tarjan(1,0);for(int i=1;i<=tn;i++)pa[i]=i; 155 for(int i=1;i<=n;i++){ 156 if(poi[i]){ 157 val1[bel1[i]]=1; 158 if(getpa(bel[i])!=getpa(bel1[i])){init(bel[i],bel1[i]);init(bel1[i],bel[i]);merpa(bel1[i],bel[i]);} 159 }else dfs1(i); 160 /*cout<<bel[i]<<bel1[i]<<poi[i]<<endl;*/ 161 } 162 for(int i=1;i<=n;i++){ 163 if(poi[i])dfs11(i); 164 } 165 dfs(1,0); 166 int q;scanf("%d",&q); 167 for(int i=1;i<=q;i++)solve(); 168 } 169 return 0; 170 }