博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【洛谷P2607】[ZJOI2008]骑士
阅读量:5245 次
发布时间:2019-06-14

本文共 1622 字,大约阅读时间需要 5 分钟。

骑士

这道题一看,似乎和是一样的,然而它并没有保证是一棵树

但是,对于每个连通块,必有相同的点数和边数,这样的图一定是一棵树上加一条边

这条边一定回使图中形成一个环,这种图貌似叫“基环树”。。

我们只要将不同的连通块分开处理,最后相加即可

对于一个基环树,只要找到环上的一条边,把它“拆掉”,分别从两个顶点dp一下就行了,

由于一条边的两个顶点不能同时选,就将f[u][0]与f[v][0]取一个max即可

#include
#include
#include
#include
using namespace std;#define MAXN 1000100int n,value[MAXN],Head[MAXN],num=1,root1,root2,cut=-1;long long dp[MAXN][2],ans;bool vis[MAXN];struct NODE{ int to,next;} e[MAXN<<1];inline int read(){ int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } return x;}inline void add(int x,int y){ e[++num].to=y; e[num].next=Head[x]; Head[x]=num;}void dfs(int t,int last){  //找环 vis[t]=1; for(int i=Head[t];i;i=e[i].next) if(e[i].to!=last){ if(!vis[e[i].to]) dfs(e[i].to,t); else { cut=i; root1=t; root2=e[i].to; } }}void solve(int t,int last)  //舞会{ dp[t][0]=0; dp[t][1]=value[t]; for(int i=Head[t];i;i=e[i].next) if(e[i].to!=last&&i!=cut&&i!=(cut^1)) { int v=e[i].to; solve(v,t); dp[t][0]+=max(dp[v][1],dp[v][0]); dp[t][1]+=dp[v][0]; }}int main(){ scanf("%d",&n); int y; for(int i=1;i<=n;i++){ scanf("%d%d",&value[i],&y); add(i,y); add(y,i); } for(int i=1;i<=n;i++) if(!vis[i]){ dfs(i,-1); solve(root1,-1); long long t=dp[root1][0]; solve(root2,-1); ans+=max(t,dp[root2][0]); } printf("%lld\n",ans); return 0;}

 

转载于:https://www.cnblogs.com/yjkhhh/p/9218052.html

你可能感兴趣的文章
MacOS copy图标shell脚本
查看>>
国外常见互联网盈利创新模式
查看>>
Oracle-05
查看>>
linux grep 搜索查找
查看>>
Not enough free disk space on disk '/boot'(转载)
查看>>
android 签名
查看>>
vue项目中使用百度统计
查看>>
android:scaleType属性
查看>>
SuperEPC
查看>>
CentOS7安装iptables防火墙
查看>>
mysql-5.7 innodb 的并行任务调度详解
查看>>
shell脚本
查看>>
Upload Image to .NET Core 2.1 API
查看>>
Js时间处理
查看>>
Java项目xml相关配置
查看>>
三维变换概述
查看>>
第三次作业
查看>>
vue route 跳转
查看>>
【雷电】源代码分析(二)-- 进入游戏攻击
查看>>
Entityframework:“System.Data.Entity.Internal.AppConfig”的类型初始值设定项引发异常。...
查看>>