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

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

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

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=;
int n,m;
struct nod{
int y,next;
};nod e1[maxn*];nod e[maxn*];nod e2[maxn*];
int head1[maxn]={},head[maxn]={},tot1=,tot=;
int head2[maxn]={},tot2=;
int dfn[maxn]={},low[maxn]={},bel[maxn]={},bel1[maxn]={},poi[maxn]={},sta[maxn]={},tai,cnt,tn;
int val[maxn]={};
int pa[maxn]={};
void init1(int x,int y){ e1[++tot1].y=y;e1[tot1].next=head1[x];head1[x]=tot1; }
void init(int x,int y){ e[++tot].y=y;e[tot].next=head[x];head[x]=tot; }
void init2(int x,int y){ e2[++tot2].y=y;e2[tot2].next=head2[x];head2[x]=tot2; }
int getpa(int x){return x==pa[x]?x:getpa(pa[x]);}
void merpa(int x,int y){
x=getpa(x);y=getpa(y);
pa[x]=pa[y];
}
void Tarjan(int x,int p){
dfn[x]=low[x]=++cnt;sta[++tai]=x; int z=;
for(int i=head1[x];i;i=e1[i].next){
if(e1[i].y==p)continue;
if(!dfn[e1[i].y]){
Tarjan(e1[i].y,x);
low[x]=min(low[e1[i].y],low[x]);
if(low[e1[i].y]>=dfn[x]){
int w; ++tn;++z;
if(low[e1[i].y]==dfn[x]&&!p)bel[x]=tn;
do{
w=sta[tai--];
bel[w]=tn;
}while(w!=e1[i].y);
}
}
else low[x]=min(low[x],dfn[e1[i].y]);
}
if(z>=&&p){
poi[x]=;
bel1[x]=++tn;
}
if(!p){
if(z>){poi[x]=;bel1[x]=++tn;}
if(!bel[x])bel[x]=++tn;
}
}
void dfs1(int x){
for(int i=head1[x];i;i=e1[i].next){
int y=e1[i].y;
if(poi[y]){
if(getpa(bel1[y])!=getpa(bel[x])){
init(bel1[y],bel[x]);init(bel[x],bel1[y]);
merpa(bel1[y],bel[x]);
}
}
}
}
void dfs11(int x){
for(int i=head1[x];i;i=e1[i].next){
int y=e1[i].y;
if(poi[y]){
if(getpa(bel1[y])!=getpa(bel1[x])){
init(bel1[y],bel1[x]);init(bel1[x],bel1[y]);
merpa(bel1[y],bel1[x]);
}
}
}
}
int dep[maxn]={},fa[maxn][]={},id[maxn]={},shu;
int a[maxn]={},val1[maxn];
void dfs(int x,int p){
dep[x]=dep[p]+;fa[x][]=p;val[x]=val[p]+val1[x];id[x]=++shu;
//cout<<x<<shu<<endl;
for(int i=;i<=;i++)fa[x][i]=fa[fa[x][i-]][i-];
for(int i=head[x];i;i=e[i].next){
if(e[i].y==p)continue;
dfs(e[i].y,x);
}
}
bool mcmp(int x,int y){
return id[x]<id[y];
}
int getlca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
if(dep[x]!=dep[y])for(int i=;i>=;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=;i>=;i--)if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}
return fa[x][];
}
int dfs2(int x){
int ans=;//cout<<x<<endl;
for(int i=head2[x];i;i=e2[i].next){//cout<<x<<e2[i].y<<endl;
ans+=dfs2(e2[i].y);
ans+=val[e2[i].y]-val[x];
}
return ans;
}
void dfs3(int x){
for(int i=head2[x];i;i=e2[i].next){
dfs3(e2[i].y);
}head2[x]=;
}
void solve(){
int nm;scanf("%d",&nm);
int tly=,w=;
for(int i=;i<=nm;i++){ scanf("%d",&a[i]); if(poi[a[i]]){a[i]=bel1[a[i]]; }else a[i]=bel[a[i]];}
sort(a+,a++nm,mcmp);
for(int i=;i<=nm;i++)if(a[tly]!=a[i])a[++tly]=a[i];
tot2=;tai=;sta[]=a[];w-=val1[a[]];
for(int i=;i<=tly;i++){
int lc=getlca(sta[tai],a[i]);w-=val1[a[i]];//cout<<a[i]<<sta[tai]<<lc<<endl;
while(tai&&dep[lc]<dep[sta[tai]]){
if(tai==||(tai>&&dep[sta[tai-]]<dep[lc])){
init2(lc,sta[tai]);tai--;break;
}
if(tai->)init2(sta[tai-],sta[tai]);
tai--;
}
if(sta[tai]!=lc||!tai)sta[++tai]=lc;
if(sta[tai]!=a[i]||!tai)sta[++tai]=a[i];
}
while(--tai){init2(sta[tai],sta[tai+]);}
w+=dfs2(sta[]); dfs3(sta[]);
//cout<<tly<<' '<<a[1]<<' '<<a[2]<<endl;
//cout<<sta[1]<<' '<<getlca(a[1],a[2])<<endl;
w+=val1[sta[]];
cout<<w<<endl;
}
int main(){
//freopen("game.in","r",stdin);
//freopen("game.out","w",stdout);
int T;scanf("%d",&T);
while(T-->){
scanf("%d%d",&n,&m);
memset(dfn,,sizeof(dfn));
memset(poi,,sizeof(poi));
memset(low,,sizeof(low));
memset(bel,,sizeof(bel));
memset(bel1,,sizeof(bel1));
memset(head1,,sizeof(head1));
memset(head2,,sizeof(head2));
memset(head,,sizeof(head));
memset(fa,,sizeof(fa));
memset(val,,sizeof(val));
memset(val1,,sizeof(val1));
tot1=,tot2=,tot=;cnt=;tn=;tai=;shu=;
int x,y;
for(int i=;i<=m;i++){scanf("%d%d",&x,&y);if(x==y)continue;init1(x,y);init1(y,x);}
Tarjan(,);for(int i=;i<=tn;i++)pa[i]=i;
for(int i=;i<=n;i++){
if(poi[i]){
val1[bel1[i]]=;
if(getpa(bel[i])!=getpa(bel1[i])){init(bel[i],bel1[i]);init(bel1[i],bel[i]);merpa(bel1[i],bel[i]);}
}else dfs1(i);
/*cout<<bel[i]<<bel1[i]<<poi[i]<<endl;*/
}
for(int i=;i<=n;i++){
if(poi[i])dfs11(i);
}
dfs(,);
int q;scanf("%d",&q);
for(int i=;i<=q;i++)solve();
}
return ;
}

Luogu P4606 [SDOI2018] 战略游戏 圆方树 虚树的更多相关文章

  1. bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树)

    bzoj5315/luoguP4517 [SDOI2018]战略游戏(圆方树,虚树) bzoj Luogu 题目描述略(太长了) 题解时间 切掉一个点,连通性变化. 上圆方树. $ \sum |S| ...

  2. [SDOI2018]战略游戏 圆方树,树链剖分

    [SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...

  3. BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)

    Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...

  4. Luogu4606 SDOI2018 战略游戏 圆方树、虚树、链并

    传送门 弱化版 考虑到去掉一个点使得存在两个点不连通的形式类似割点,不难想到建立圆方树.那么在圆方树上对于给出的关键点建立虚树之后,我们需要求的就是虚树路径上所有圆点的数量减去关键点的数量. 因为没有 ...

  5. BZOJ.5329.[SDOI2018]战略游戏(圆方树 虚树)

    题目链接 显然先建圆方树,方点权值为0圆点权值为1,两点间的答案就是路径权值和减去起点终点. 对于询问,显然可以建虚树.但是只需要计算两关键点间路径权值,所以不需要建出虚树.统计DFS序相邻的两关键点 ...

  6. luogu P4606 [SDOI2018]战略游戏

    LINK:战略游戏 一道很有价值的题目.这道题 一张无向联通图 每次询问给出K个关键点 问摧毁图中哪个点可以使得这K个关键的两两之间有一对不能联通 去掉的这个点不能是关键点 求方案数. 可以发现 当K ...

  7. [bzoj5329] P4606 [SDOI2018]战略游戏

    P4606 [SDOI2018]战略游戏:广义圆方树 其实会了圆方树就不难,达不到黑,最多算个紫 那个转换到圆方树上以后的处理方法,画画图就能看出来,所以做图论题一定要多画图,并把图画清楚点啊!! 但 ...

  8. 洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】

    题目链接 洛谷P4606 双倍经验:弱化版 题解 两点之间必经的点就是圆方树上两点之间的圆点 所以只需建出圆方树 每次询问建出虚树,统计一下虚树边上有多少圆点即可 还要讨论一下经不经过根\(1\)的情 ...

  9. 洛谷P4606 [SDOI2018]战略游戏 [广义圆方树]

    传送门 思路 先考虑两点如何使他们不连通. 显然路径上所有的割点都满足条件. 多个点呢?也是这样的. 于是可以想到圆方树.一个点集的答案就是它的虚树里圆点个数减去点集大小. 可以把点按dfs序排序,然 ...

随机推荐

  1. tomcat集群及session共享

    一般来说,java web app主要用作两个领域: 1.api.api一般是无状态的,所以无需考虑session共享的问题 2.传统web应用和网站,如crm,oa,erp,b2c,bbs等.尤其b ...

  2. springboot集成mybatis环境搭建以及实现快速开发微服务商品模块基本的增删改查!

    之前学习了springboot和mybatis3的一些新特性,初步体会了springboot的强大(真的好快,,,,,),最近趁着复习,参考着以前学习的教程,动手写了一个springboot实战的小例 ...

  3. 【HASPDOG】hasp_update参数f和i区别

    [root@BICServer-TX shared]# ./hasp_update This is a simple demo program for the Sentinel Update and ...

  4. Serv-U 的升级及数据备份和迁移【转】

    Serv-U 配置备份   在serv-u7.x及以上版本安装目录下,有一个文件Serv-U.Archive是serv-u的配置文件,有一个users文件夹是Serv-U的域和用户的信息,那么我们只需 ...

  5. WPF中ListBox的绑定

    WPF中列表式控件派生自ItemsControl类,继承了ItemsSource属性.ItemsSource属性可以接收一个IEnumerable接口派生类的实例作为自己的值(所有可被迭代遍历的集合都 ...

  6. Python之 Lambda表达式

    标签(空格分隔): Python进阶 Lambda是一种匿名函数,当我们需要重复调用某一函数,又不想写那么多代码时可以使用lambda表达式来代替. lambda的通用格式: lambda argum ...

  7. mybatis比hibernate处理速度快的原因

    mybatis:是面向结果集的.当要展示的页面需要几个字段时,springmvc会提供这几个字段并将其拼接成结果集,在转化为相应的对象. hibernate:是面向对象的.要展示的页面需要某些字段时, ...

  8. Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.

    在设置请求头的时候报这个Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPE ...

  9. pip离线安装

    pip freeze > requirements.txt pip download <packages> pip install --no-index --find-links=& ...

  10. python面向对象(四)之抽象类与接口

    ​ 学过java的应该知道java有抽象类和接口的那么python呢?(以前写的关于java抽象类的笔记java抽象类与接口) python作为一个动态语言,没有强类型的检查,而是以鸭子类型的方式提现 ...