Luogu P4606 [SDOI2018] 战略游戏 圆方树 虚树

https://www.luogu.org/problemnew/show/P4606

把原来的图的点双联通分量缩点(每个双联通分量建一个点,每个割点再建一个点)(用符合逻辑的方式)建一棵树(我最开始建的想法就有问题,答案竟然还差不多,查了好久才发现……然后重新想了个正确的建法发现比之前那个错误的建法好写多了,气),然后把这棵树整成虚树再做个树上dp就(安排得)明明白白的了。dp的时候注意一下树的根的值也要统计。

我的程序大概常数太大了洛谷开O2才能过,BZOJ会tle,也不想改了,就这样吧……

  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 }
View Code

猜你喜欢

转载自www.cnblogs.com/137shoebills/p/9070272.html