zoukankan      html  css  js  c++  java
  • 仙人掌学习笔记

    定义:

    • 是一个连通图。
    • 每一条边最多属于一个简单环。

    做法:

    DFS树

    根据 (tarjan) 的过程,得到一个(DFS)树,同时也可以可得到每个点属于哪一个环(或不属于任何一个环)。对于只属于树的边,进行树形DP;对于环上的边,在环上DP。适用于仅需操作一次的简单仙人掌DP。
    代码框架如下(以求仙人掌直径为例):

    void dp(int x,int y) {//环上DP
    	cnt=0; for(int i=y;i!=x;i=fa[i]) a[++cnt]=f[i]; a[++cnt]=f[x];//处理出环上的点
    	for(int i=1;i<=cnt/2;i++)	swap(a[i],a[cnt-i+1]);
    	for(int i=cnt+1;i<=cnt+cnt/2;i++) a[i]=a[i-cnt];//复制原串
    	q[F=E=1]=1;//单调队列优化DP
    	for(int i=2;i<=cnt+cnt/2;i++) {
    		if(F<=E&&i-q[F]>cnt/2)	++F;
    		ans=Max(ans,a[q[F]]+a[i]+i-q[F]);
    		while(F<=E&&a[i]-i>=a[q[E]]-q[E]) --E;
    		q[++E]=i;
    	}
    	for(int i=2;i<=cnt;i++) f[x]=Max(f[x],a[i]+Min(i-1,cnt-i+1));//更新
    }
    
    void dfs(int u,int ff) {//模拟tarjan的过程
    	dfn[u]=low[u]=++idx,f[u]=0;//f[i]为DP的状态
    	for(int i=0;i<e[u].size();i++) {//枚举每条出边
    		if(e[u][i]==ff)	continue;//判掉父亲
    		if(!dfn[e[u][i]])//未访问过,加边建DFS树
    			fa[e[u][i]]=u,dfs(e[u][i],u),low[u]=Min(low[u],low[e[u][i]]);
    		else low[u]=Min(low[u],dfn[e[u][i]]);//更新该节点能回到的最早的点
    		if(low[e[u][i]]>dfn[u])//进行简单的树形DP
    			ans=Max(ans,f[u]+f[e[u][i]]+1),f[u]=Max(f[u],f[e[u][i]]+1);
    	}
    	for(int i=0;i<e[u].size();i++)//查找仙人掌上的儿子但不是DFS树上的儿子的点,即形成环
    		if(e[u][i]!=ff&&fa[e[u][i]]!=u&&dfn[e[u][i]]>dfn[u]) dp(u,e[u][i]);//进行环上DP
    }
    

    例题:
    SHOI2008 cactus仙人掌图
    小C的独立集
    HNOI2009 无归岛


    圆方树

    (听说广义圆方树可以处理一些图的问题,如 【CF Round #278】Tourists, APIO2018 Duathlon 铁人两项)

    留坑待填

  • 相关阅读:
    第3次作业:卷积神经网络
    第一次作业:深度学习基础
    CSS基础总结
    Java 9.Spring--AOP
    Java 8.Spring--整合Junit测试
    Java 7.Spring--使用注解
    Java 6.Spring--对象的依赖关系-复杂类型注入
    Java 5.Spring的依赖注入
    Java 4.Spring的对象创建的方法
    Java 3.Spring的对象创建的细节
  • 原文地址:https://www.cnblogs.com/daniel14311531/p/10246731.html
Copyright © 2011-2022 走看看