题目链接:点击查看

题目大意:给出一个由n个点和m条边构成的无向图,每个点都有一个权值,现在给出起点st,问从起点出发,如何规划路线可以使得途径的权值最大,唯一的约束是一条边不能连续经过,比如当前从u->v,下一次不可以从v->u

题目分析:首先要理解好题目,题目中的一条边不能连续经过两次,不代表只能经过两次,换句话说,若几个点可以构成环,那么他们就可以在环上跑一圈然后再出去,所以我们可以先缩点,因为是无向图,我们选择边双缩点,只要缩点后的集合中的点大于一个点的话,那么当前集合肯定能构成环,缩点后整个图变成了一棵树,我们就可以直接设计dp了,因为如果一个点有环的话是可以多次经过的,那么我们不妨可以将所有新点内大于1的集合压缩至其父亲,以至于让dp写起来更简单,完成压缩后自底向上维护一条链上的最大值就好了

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e5+100;const int M=4e5+100;struct Egde
{int to,next;
}edge1[M],edge2[M];int head1[N],head2[N],low[N],dfn[N],c[N],num,cnt1,cnt2,dcc,n,m,sz[N];LL w[N],val[N],dp[N],mmax;bool bridge[M];void addedge1(int u,int v)
{edge1[cnt1].to=v;edge1[cnt1].next=head1[u];head1[u]=cnt1++;
}void addedge2(int u,int v)
{edge2[cnt2].to=v;edge2[cnt2].next=head2[u];head2[u]=cnt2++;
}void tarjan(int u,int in_edge)
{dfn[u]=low[u]=++num;for(int i=head1[u];i!=-1;i=edge1[i].next){int v=edge1[i].to;if(!dfn[v]){tarjan(v,i);low[u]=min(low[u],low[v]);if(low[v]>dfn[u])bridge[i]=bridge[i^1]=true;}else if(i!=(in_edge^1))low[u]=min(low[u],dfn[v]);}
}void dfs(int u)
{c[u]=dcc;sz[dcc]++;val[dcc]+=w[u];for(int i=head1[u];i!=-1;i=edge1[i].next){int v=edge1[i].to;if(c[v]||bridge[i])continue;dfs(v);}
}void solve()
{for(int i=1;i<=n;i++)//找桥 if(!dfn[i])tarjan(i,0);for(int i=1;i<=n;i++)//缩点 if(!c[i]){dcc++;dfs(i);}
}void dfs1(int u,int fa)
{for(int i=head2[u];i!=-1;i=edge2[i].next){int v=edge2[i].to;if(v==fa)continue;dfs1(v,u);if(sz[v]>1){sz[u]+=sz[v];val[u]+=val[v];val[v]=0;} }
}void dfs2(int u,int fa)
{dp[u]=val[u];for(int i=head2[u];i!=-1;i=edge2[i].next){int v=edge2[i].to;if(v==fa)continue;dfs2(v,u);dp[u]=max(dp[u],dp[v]+val[u]);}
}void build()//缩点+连边
{solve();for(int i=2;i<cnt1;i+=2){int u=edge1[i^1].to;int v=edge1[i].to;if(c[u]==c[v])continue;addedge2(c[u],c[v]);addedge2(c[v],c[u]);}
}void init()
{cnt1=2;cnt2=num=dcc=0;memset(head2,-1,sizeof(head2));memset(head1,-1,sizeof(head1));memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));memset(bridge,false,sizeof(bridge));memset(c,0,sizeof(c));
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);init();scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%lld",w+i);while(m--){int u,v;scanf("%d%d",&u,&v);addedge1(u,v);addedge1(v,u);}int st;scanf("%d",&st);build();dfs1(c[st],-1);dfs2(c[st],-1);printf("%lld\n",dp[c[st]]);return 0;
}

CodeForces - 1220E Tourism(边双缩点+树形dp)相关推荐

  1. 中石油训练赛 - Plan B(点双缩点+树形dp)

    题目大意:给出一张 n 个点 m 条边的无向连通图,现在有某些点被标记了,问能否通过删除某个未被标记的点,使得删除该点后的数个互不相交的连通块中,至少存在一个联通块中不含有被标记的点 题目分析:首先不 ...

  2. codeforces 816 E. Karen and Supermarket(树形dp)

    题目链接:http://codeforces.com/contest/816/problem/E 题意:有n件商品,每件有价格ci,优惠券di,对于i>=2,使用di的条件为:xi的优惠券需要被 ...

  3. Codeforces 835 F Roads in the Kingdom(树形dp)

    F. Roads in the Kingdom(树形dp) 题意: 给一张n个点n条边的无向带权图 定义不便利度为所有点对最短距离中的最大值 求出删一条边之后,保证图还连通时不便利度的最小值 $n & ...

  4. [Codeforces 814D] An overnight dance in discotheque 树形dp,贪心

    题目链接 题解:这道题,首先可以发现,圆与圆关系只有内含与外离, 所以可以建立出一个树形结构, 每个圆的父亲是与这个圆半径相差最小且包含这个圆的圆, 这样,整个一张图形成了一个森林,可以将圆按半径排序 ...

  5. Codeforces 1088E Ehab and a component choosing problem(树形DP)

    Codeforces 1088E Ehab and a component choosing problem(树形DP) 题意 给一棵树,要求从中选一些联通分量,使得平均联通分量重量总和最大.如果有多 ...

  6. 中石油训练赛 - One-Way Conveyors(边双缩点+树上差分)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边的无向图,现在需要将这张图转换为有向图,并且使得 k 个可达条件成立,输出一种构造方案 题目分析:如果在无向图中出现环的话,那么在转换为有向图 ...

  7. HDU - 4612 Warm up(边双缩点+树的直径)

    题目链接:点击查看 题目大意:给出一个由n个点和m条边构成的无向图,现在允许加一条边,使得整张图中桥的数量最少,求最少的桥的数量 题目分析:因为是要求桥,所以直接用tarjan边双缩点,将原图转换成一 ...

  8. POJ - 3177 Redundant Paths(边双缩点)

    题目链接:点击查看 题目大意:给出一个由n个点和m条边构成的无向图,现在问至少添加几条边,才能使得任意两点之间都能由至少两条不同的路到达 题目分析:既然要让任意两点之间至少由两条道路连接,换句话说也就 ...

  9. 无向图缩点:tarjan点双与边双缩点(模板)

    e-DCC边双缩点:(用之前记得init) cnt1是从2开始的 边双缩点可以将无向图转换为一个森林,如果原图保证连通的话,那么可以转换为一棵树 const int N=1e4+100;const i ...

最新文章

  1. aaronyang的百度地图API之LBS云 笔记[开发准备]
  2. 基于Java多线程操作文件案例分享
  3. 获取后台数据-Http
  4. python 3.7.3 thinker_GitHub - thinkerwalker/python3-bin
  5. 看准网点评没有了_大众点评“亡”于2020
  6. [OS复习]设备管理1
  7. LeetCode 81 搜索旋转排序数组 II
  8. JeecgBoot 常见问题QA
  9. 标签选择器与字体连写
  10. html 获取mac地址,Javascript获取Mac地址
  11. 席位分配:惯例Q值法,dhondt法matlab实现
  12. 在项目中集成hibernate遇到的问题(4)
  13. Python 数据挖掘(四) pandas模块 简单使用
  14. 16进制颜色转换RGB原理
  15. android 设置闹钟,android 设置闹钟
  16. php screw.so,php screw加密
  17. 方程组在原点附近解matlab,前置血管常发生于A.副胎盘B.胎盘血管瘤C.双叶胎盘D.帆状胎盘...
  18. 学术捜索新添找寻新近文章功能
  19. kerastensorflow+分布式训练︱实现简易视频内容问答框架
  20. OJ刷题 |超大目标值(1亿)求质数个数问题

热门文章

  1. MySQL服务端的登录和退出
  2. MySQL高级 - 内存优化 - InnoDB内存优化
  3. MySQL 的发展历史和版本分支:
  4. 为什么要用MyBatis-JDBC 连接数据库
  5. RocketMQ环境搭建
  6. 数据库-优化-数据库结构的优化-拆分优化
  7. K8S-statefulset-nacos
  8. python关闭文件os_如何关闭使用os.startfile(),Python 3.6打开的文件
  9. pythonfor循环range_python之for循环与range()函数
  10. alias用法和对当前用户的永久配置