bzoj 1791 DP
首先对于一棵树我们可以tree_dp来解决这个问题,那么对于环上每个点为根的树我们可以求出这个树的一端为根的最长链,并且在tree_dp的过程中更新答案。那么我们对于环,从某个点断开,破环为链,然后再用DP来解决这个问题。
备注:很久之前的一道题,刚转的c++,然后T了,也懒得改了。
/**************************************************************
Problem: 1791
User: BLADEVIL
Language: C++
Result: Time_Limit_Exceed
****************************************************************/ //By BLADEVIL
#include <cstdio>
#include <cstring>
#define maxn 1000010
#define LL long long using namespace std; LL n,time,l;
LL other[maxn<<],last[maxn],pre[maxn<<],dfn[maxn],low[maxn],vis[maxn],que[maxn],a[maxn],xx[maxn];
LL ans;
LL len[maxn<<],max1[maxn],max2[maxn],sum[maxn],w[maxn],yy[maxn],maxlen[maxn];
LL save; void getmin(LL &x,LL y)
{if (y<x) x=y;} void connect(LL x,LL y,LL z) {
pre[++l]=last[x];
last[x]=l;
other[l]=y;
len[l]=z;
//if (y>x) printf("%d %d %lld\n",x,y,z);
} void dfs(LL x,LL fa) {
dfn[x]=low[x]=++time;
for (LL q=last[x];q;q=pre[q]) {
if (other[q]==fa) continue;
if (!low[other[q]]) {
dfs(other[q],x);
getmin(low[x],low[other[q]]);
} else getmin(low[x],dfn[other[q]]);
}
if (low[x]!=dfn[x]) save=low[x];
} void dp(LL x) {
memset(que,,sizeof que);
LL h=,t=1ll;
que[]=x; vis[x]=1ll;
while (h<t) {
LL cur=que[++h];
for (LL q=last[cur];q;q=pre[q]) {
if (low[other[q]]==low[x]) continue;
if (vis[other[q]]) continue;
vis[other[q]]=vis[cur]+1ll;
que[++t]=other[q];
}
}
//for (LL i=1;i<=t;i++) printf("%d ",que[i]); printf("\n");
for (LL i=t;i;i--)
for (LL q=last[que[i]];q;q=pre[q]) {
if (low[other[q]]==low[x]) continue;
if (vis[other[q]]!=vis[que[i]]+) continue;
//printf(" %d %d\n",que[i],other[q]);
if (max1[other[q]]+len[q]>max1[que[i]])
max2[que[i]]=max1[que[i]],max1[que[i]]=max1[other[q]]+len[q]; else
if (max1[other[q]]+len[q]>max2[que[i]]) max2[que[i]]=max1[other[q]]+len[q];
if (max1[other[q]]+max2[other[q]]>maxlen[que[i]])
maxlen[que[i]]=max1[other[q]]+max2[other[q]];
if (max1[que[i]]+max2[que[i]]>maxlen[que[i]])
maxlen[que[i]]=max1[que[i]]+max2[que[i]];
if (maxlen[que[i]]<maxlen[other[q]]) maxlen[que[i]]=maxlen[other[q]];
}
//for (LL i=1;i<=t;i++) printf("%d %lld %lld %lld\n",que[i],max1[que[i]],max2[que[i]],maxlen[que[i]]);
} void solve(LL x) {
LL now=0ll;
dfs(x,-);
//printf("%d",save);
if (save)
for (LL i=;i<=n;i++) if (low[i]==save) x=i;
save=;
/*if (xx[xx[x]]==x)
{
ans+=(yy[x]>yy[xx[x]])?yy[x]:yy[xx[x]];
return;
}*/
LL cur;
for (LL i=;i<=n;i++) if (low[i]==low[x]) dp(i),cur=i;
//printf(" %lld\n",max1[x]);
LL t=; a[t]=cur;
while () {
for (LL q=last[a[t]];q;q=pre[q]) {
now=(maxlen[a[t]]>now)?maxlen[a[t]]:now;
if (low[other[q]]!=low[x]) continue;
if (other[q]==a[t-]) continue;
a[++t]=other[q]; sum[t]=len[q]; break;
}
if (a[t]==cur) break;
}
//printf(" %d ",x);
//for (LL i=1;i<=t;i++) printf(" %lld %d %d\n",max1[a[i]],a[i],sum[i]);
t--;
for (LL i=;i<=t;i++) a[i+t]=a[i],sum[i+t]=sum[i];
t*=;
//for (LL i=1;i<=t;i++) printf(" %lld %d %d\n",max1[a[i]],a[i],sum[i]);
for (LL i=;i<=t;i++) sum[i]+=sum[i-];
LL len=t>>1ll;
memset(que,,sizeof que);
LL l=,r=; que[]=;
for (LL i=;i<=t;i++) {
if (i-que[l]+>len) l++;
w[i]=max1[a[que[l]]]+max1[a[i]]+sum[i]-sum[que[l]];
//printf("w[i]=%d",w[i]); printf(" %d %d\n",i,que[l]);
while (l<=r&&(max1[a[i]]-sum[i]>max1[a[que[r]]]-sum[que[r]])) r--;
que[++r]=i;
//for (LL i=l;i<=r;i++) printf("|%d ",que[i]); printf("\n");
}
for (LL i=;i<=t;i++) now=(w[i]>now)?w[i]:now;
//printf(" %lld ",ans);
ans+=now;
} int main() {
scanf("%d",&n);
for (LL i=;i<=n;i++) scanf("%d%lld",&xx[i],&yy[i]);
for (LL i=;i<=n;i++) {
if (xx[i]==i) continue;
if (xx[xx[i]]==i&&xx[i]>i) yy[i]=(yy[xx[i]]>yy[i])?yy[xx[i]]:yy[i],yy[xx[i]]=-1ll;
}
for (LL i=;i<=n;i++) if (yy[i]!=-) connect(i,xx[i],yy[i]),connect(xx[i],i,yy[i]);
for (LL i=;i<=n;i++) if (!low[i]) solve(i);
//for (LL i=1;i<=n;i++) printf(" %d %d %d\n",i,low[i],dfn[i]);
printf("%lld\n",ans);
return ;
}
bzoj 1791 DP的更多相关文章
- bzoj 3622 DP + 容斥
LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[ ...
- BZOJ 1791 岛屿(环套树+单调队列DP)
题目实际上是求环套树森林中每个环套树的直径. 对于环套树的直径,可以先找到这个环套树上面的环.然后把环上的每一点都到达的外向树上的最远距离作为这个点的权值. 那么直径一定就是从环上的某个点开始,某个点 ...
- bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】
我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...
- BZOJ - 1003 DP+最短路
这道题被马老板毒瘤了一下,TLE到怀疑人生 //然而BZOJ上妥妥地过了(5500ms+ -> 400ms+) 要么SPFA太玄学要么是初始化block被卡到O(n^4) 不管了,不改了 另外D ...
- 「BZOJ 1791」「IOI 2008」Island「基环树」
题意 求基环树森林所有基环树的直径之和 题解 考虑的一个基环树的直径,只会有两种情况,第一种是某个环上结点子树的直径,第二种是从两个环上结点子树内的最深路径,加上环上这两个结点之间的较长路径. 那就找 ...
- BZOJ 2431 & DP
题意:求逆序对数量为k的长度为n的排列的个数 SOL: 显然我们可以对最后一位数字进行讨论,判断其已经产生多少逆序对数量,然后对于前n-1位同样考虑---->每一个长度的排列我们都可以看做是相同 ...
- bzoj 1791: [Ioi2008]Island 岛屿
#include<iostream> #include<cstdio> #define M 1000009 using namespace std; *M],cnt,n,hea ...
- 【BZOJ 1791】 [Ioi2008]Island 岛屿
Description 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样 ...
- bzoj 1592 dp
就是dp啊 f[i][j]表示到第i位,最后一位高度是j的最小花费 转移::f[i][j]=minn(f[i-1][k])+abs(a[i]-num[j]);(k<=j) #include< ...
随机推荐
- 第2章 面向对象的设计原则(SOLID):5_迪米特法则
5. 迪米特法则(Law of Demeter,LoD) 5.1 定义 (1)应尽量减少其他对象之间的交互,对象只和自己的朋友交谈,即对其他依赖的类越少越好(不要和太多的类发生关系). (2)尽量不要 ...
- js实现复制功能
JS 点击复制Copy 1.实现点击按钮,复制文本框中的的内容 1 <script type="text/javascript"> 2 function copyUrl ...
- S2小测--索引--视图
1. 关于Sql server 视图 视图是一个虚拟表,我们在查询视图的时候,实际上是对基础表的查询.视图不仅可以作为SELECT查询的目标,也可以作为修改语句的目 标.理论上它可以像普通的物理表一 ...
- 16SpringMvc_在业务控制方法中写入User,Admin多个模型收集参数——引出问题
上面文章时普通的业务那个方法中收集一个实体类,这篇文章想收集两个实体类. 文本要做的是:在person.jsp页面上,有两个表单.分别是普通用户和管理员用户的表单(普通用户的表单和管理员用户的表单里面 ...
- 如何“刷leetcode”
做题目的: 获得 offer 巩固算法与数据结构知识,将学到的东西用出来 如何做题: 根据章节与难度来做. 比如你学了 linked list,就去找到标签为 linked list 的题目,然后根据 ...
- mvc control 请求两次问题
今天在做项目时,突然发现一个mvc 的control中action被执行了两次,最终发现是由于favicon.ico导致的.问题代码: <link rel="shortcut icon ...
- Spring MVC的工作流程
前端控制器(DispatcherServlet): (不需要我们开发)接收请求,响应结果,相当于转发器,中央处理器.减少了其它组件之间的耦合度. springmvc.xml是SpringMVC的一个全 ...
- git的简介,安装以及使用
1git的简介 Git是什么? Git是目前世界上最先进的分布式版本控制系统(没有之一). Git有什么特点?简单来说就是:高端大气上档次! 2Linus一直痛恨的CVS及SVN都是集中式的版本控制系 ...
- 解放双手:如何在本地调试远程服务器上的Node代码
写在前面 谈到node断点调试,目前主要有三种方式,通过node内置调试工具.通过IDE(如vscode).通过node-inspector,三者本质上差不多.本文着重点在于介绍 如何在本地通过nod ...
- windows API 开发飞机订票系统 图形化界面 (四)
接下来的是录入航班.修改航班信息功能的实现: //录入航班 BOOL EntryFlight(HWND hEntryDlg){ TCHAR szDiscount[]; TCHAR szFare[],s ...