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< ...
随机推荐
- SpringBoot 快速入门
本篇文章翻译来源为:http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ 首先springboot ...
- MongoDB学习(四)客户端工具备份数据库
在上一篇MongoDB学习(三)中讲解了如何在服务器端进行数据的导入导出与备份恢复,本篇介绍下如何利用客户端工具来进行远程服务器的数据备份到本地. 以客户端工具MongoVUE为例来进行讲解: 1.首 ...
- SVN和git的使用(附github的简单玩法)
今天简单的总结了下SVN和git的使用,也尝试了下github,应该好好提高下自己的英文水平了,梦想有一天不再使用任何翻译软件. [svn]:集中式的代码管理工具(版本控制工具--版本记录) 1> ...
- dos命令行连接数据库
dos命令行连接数据库 (2012-03-22 21:26:16) 转载▼ 标签: it C:\Adminstrator> sqlplus "/as sysdba" 查看 ...
- 20Mybatis_订单商品数据模型_一对一查询——resultType和resultMap两种方式以及两种方式的总结
上一篇文章分析了数据模型,这篇文章就给出一个需求,这个需求是一对一查询,并完成这个需求. ------------------------------------------------------- ...
- [转]Linux查看物理CPU个数、核数、逻辑CPU个数
From : http://www.cnblogs.com/emanlee/p/3587571.html # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个 ...
- Linux 进程与线程一(创建-关闭线程)
进程是一个实体.每一个进程都有他自己的内存地址段(heap,stack等等) 进程是执行中的程序. 程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体. 进程是操作系统中最基 ...
- 浅谈设计模式--单例模式(Singleton Pattern)
题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...
- activiti-explorer:使用mysql导入外部bpmn文件后存在乱码的问题
我已经采取了如下步骤,但是仍然还是乱码 1. 在mysql中创建数据库时指定使用utf8编码: CREATE DATABASE Activiti DEFAULT CHARACTER SET utf8 ...
- 20135220谈愈敏Linux Book_18
第18章 调试 调试内核艰难且风险高,关键在于对内核的深刻理解. 18.1 准备开始 需要的是: 一个bug 一个藏匿bug的内核版本 相关内核代码的知识和运气 内核中的bug不是很清晰,调试成功的关 ...