BZOJ NOI十连测 第一测 T2



思路:看到这题,就感觉是一道很熟悉的题目:
http://www.cnblogs.com/qzqzgfy/p/5535821.html
只不过这题的K最多可以到N,而且边权不再只是1,考试的时候yy了一下做法:
找k次直径,第一次把边取反,要是第二次再取到同样的边,那就把它变成0,毕竟每条边只经过2次嘛,YY的很好,实际上,交上去,5分TAT
后来听以为神犇说不是取0,而是继续取反,每条边取一次就取反一次,woc..
PS还有一点:一开始我是准备找出里面一点,然后bfs找最远和次远的点,然后把路径取反的,后面想想太SB了,毕竟这两个点是有可能有相交路径的。。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
int dis[],val[],mxdis,d[],p;
int tot,go[],next[],first[],n,k,C,cnt=,ans1,ans2,id[];
int pre[],edge[],op[],S,T,vis[],c[];
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y,int z){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
val[tot]=z;
}
void add(int x,int y,int z){
insert(x,y,z);op[tot]=tot+;insert(y,x,z);op[tot]=tot-;
}
void dfs1(int x,int fa){
d[x]=;ll mx1=,mx2=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
dfs1(pur,x);
if (d[pur]+val[i]>mx1) mx2=mx1,mx1=d[pur]+val[i];
else if (d[pur]+val[i]>mx2) mx2=d[pur]+val[i];
}
if (mxdis<mx1+mx2) mxdis=mx1+mx2,S=x;
}
void clear(int x){
for (int i=x;i!=S;i=pre[i]){
val[edge[i]]=-val[edge[i]];val[op[edge[i]]]=-val[op[edge[i]]];
}
}
int bfs(int x){
int h=,t=;
ll mx=;int Id=x;
for (int i=;i<=n;i++) dis[i]=vis[i]=pre[i]=edge[i]=c[i]=;
c[]=x;
vis[x]=;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
dis[pur]=dis[now]+val[i];
pre[pur]=now;
edge[pur]=i;
vis[pur]=;
c[++t]=pur;
}
}
for (int i=;i<=n;i++)
if (mx<dis[i]) mx=dis[i],Id=i;
return Id;
}
void clear(){
T=bfs(S);
ll sx=;int Id=S;
for (int i=;i<=n;i++)
if (i!=S&&i!=T&&sx<dis[i]) sx=dis[i],Id=i;
clear(Id);clear(T);
}
void Find_longest(){
mxdis=-0x7fffffff;
dfs1(,);
clear();
}
void dfs(int x,int fa){
int mx1=,mx2=;d[x]=;int id1=x,id2=x;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
dfs(pur,x);
if (d[pur]+val[i]>mx1) mx2=mx1,mx1=d[pur]+val[i],id2=id1,id1=id[pur];
else if (d[pur]+val[i]>mx2) mx2=d[pur]+val[i],id2=id[pur];
}
id[x]=id1;
d[x]=mx1;
if (mxdis<mx1+mx2) mxdis=mx1+mx2,ans1=id1,ans2=id2;
}
void dfss(int x,int y,int fa){
if (!x||!y) return;
if (x==y) {p=;return;}
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
dfss(pur,y,x);
if (p) {val[i]=-val[i],val[op[i]]=-val[op[i]];return;}
}
}
int main(){
while (scanf("%d",&n)!=EOF){
k=read();C=read();
tot=;
int sum=;
for (int i=;i<=n;i++) first[i]=;
for (int i=;i<n;i++){
int x=read(),y=read(),z=read();
x++;y++;
add(x,y,z);
sum+=z;
}
sum*=;
for (int i=;i<=k;i++){
mxdis=;
dfs(,);
if (mxdis<C) break;
sum=sum-mxdis+C;
p=;
dfss(ans1,ans2,);
}
printf("%d\n",sum);
}
}
然后听说有树形dp做法,由于每条边至多经过2次。假如每次穿越都新加了一条"穿越边",每次穿越都新加了2个"新点",假如子树x内有k个新点,那么(fa[x],x)这条边经过的边奇偶性和k个奇偶性相同,因为要从0出发,再回到0,这是个欧拉回路,因此进入子树p有x条边的话,离开子树p也必须是x条边,因此,奇偶性相同就得证了,由此我们设dp方程
f[x][p]代表x的子树,有p个新节点的最小代价,然后用树上背包做就好了,(虽然这看起来像n^3,但是是n^2.....)
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
int tot,go[],first[],next[],val[];
int son[],f[][],g[],n,K,C;
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y,int z){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
val[tot]=z;
}
void add(int x,int y,int z){
insert(x,y,z);insert(y,x,z);
}
void dfs(int x,int fa,int y){
son[x]=;
for (int i=;i<=n;i++) f[x][i]=inf;
f[x][]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
dfs(pur,x,val[i]);
for (int j=;j<=son[x];j++) g[j]=f[x][j],f[x][j]=inf;
for (int j=;j<son[x];j++)
for (int k=;k<=son[pur];k++)
f[x][j+k]=std::min(f[x][j+k],g[j]+f[pur][k]);
son[x]+=son[pur];
}
for (int i=son[x];i>=;i--)
f[x][i]=std::min(f[x][i],f[x][i-]);
for (int i=;i<=son[x];i++) f[x][i]+=((i%==)+)*y;
}
int main(){
while (scanf("%d",&n)!=EOF){
K=read();C=read();
tot=;
for (int i=;i<=n;i++)
first[i]=;
for (int i=;i<n;i++){
int x=read(),y=read(),z=read();
x++;y++;
add(x,y,z);
}
dfs(,,);
int ans=inf;
for (int i=;i<=K&&i*<=n;i++)
ans=std::min(ans,f[][i*]+C*i);
printf("%d\n",ans);
}
}
BZOJ NOI十连测 第一测 T2的更多相关文章
- BZOJ NOI十连测 第二测 T2
思路:20%可以搜索.. #include<algorithm> #include<cstdio> #include<cmath> #include<cstr ...
- BZOJ NOI十连测 第一测 T1
思路:首先考虑t=1的情况,t等于1,那么所有位置的颜色相同,我们不用考虑概率的问题,那么,k+d*x在模d下都相等,我们考虑预处理一个数组s[i][j],代表d为i,起始位置为j的等差数列的和,这个 ...
- BZOJ NOI十连测 第二测 T1
出题人居然是个哲学家.. 26%的程序,太SB了...本来我的想法也是二分+贪心,但是贪心是个怪怪的SX贪心.. #include<algorithm> #include<cstdi ...
- 痞子衡嵌入式:测一测i.MXRT1170 Raw NAND启动时间(从POR到进App的Reset_Handler)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 Raw NAND启动时间. 关于i.MXRT1170这颗划时代的MCU,痞子衡去年10月在其刚发布的时候, ...
- 「NOI十联测」深邃
「NOI十联测」深邃 要使得最大的连通块最小,显然先二分答案. 先固定1结点为根. 对于一个果实,显然是先处理子树中未分配的点,再向外延伸. 每个结点记录一个\(si[]\),表示子树中未分配的点数, ...
- 「NOI十联测」奥义商店
「NOI十联测」奥义商店 若lzz想花费最少的钱,那么显然要选择数目较少的颜色. 先考虑暴力的写法. 每次向两边统计,每个物品要求被买的概率可以由上一个物品推出. now=1;//now 被买概率 M ...
- 「NOI十联测」黑暗
「NOI十联测」黑暗 \(n\) 个点的无向图,每条边都可能存在,一个图的权值是连通块个数的 \(m\) 次方,求所有可能的图的权值和.(n≤30000,m≤15) 令\(ans[n][m]\)为n个 ...
- NOI十连测 第五测 T2
思路:考虑建立可持久化线段树,第一层维护的是i这个位置的next位置,第二层,维护的是接下来走这个字符会到哪个节点. 感觉很巧妙啊,不愧是Claris #include<algorithm> ...
- NOI十连测 第四测 T2
思路:线段树套可持久化treap,可持久化treap我还是第一次听说.. 改题的时候没看数据范围..乱开数组T_T #include<algorithm> #include<cstd ...
随机推荐
- sgu Kalevich Strikes Back
这道题就是求一个大矩形被n个矩形划分成n+1个部分的面积,这些矩形之间不会相交,可能包含.. #include <cstdio> #include <cstring> #inc ...
- AnimateWindow
WINDOWS提供了一个很有意思的函数:AnimateWindow.之前我想实现像MSN,QQ这些收到邮件的时候动画方式,从地下升上来的显示一个窗口,感觉很麻烦,自己去写代码,效果很不理想,今天无意中 ...
- 《Programming WPF》翻译 第8章 2.Timeline
原文:<Programming WPF>翻译 第8章 2.Timeline Timeline代表了时间的延伸.它通常还描述了一个或多个在这段时间所发生的事情.例如,在前面章节描述的动画类型 ...
- union all合并记录
SQL> SELECT empno AS 编码, ename AS 名称, nvl(mgr, deptno) AS 上级编码 FROM emp 2 order by empno 3 UNION ...
- vijos1777 引水入城
描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N行M列的矩形,其中每个格子都代表一座城市,每座城市都有一个海拔高度. 为了使居民们都尽可能 ...
- 【CF689D Friends and Subsequences】二分搜索,区间查询
题意:给定两个整数序列a,b,将a,b对齐,问有多少个区间满足a的区间内最大值等于b的区间内最小值. 数据范围:区间长度n属于[1, 200000],序列中的元素在整型范围内 思路:枚举所有n*(n+ ...
- python学习之路-1 python基础操作
本篇所涉及的内容 变量 常量 字符编码 用户交互input 格式化字符串 python的缩进规则 注释 初始模块 条件判断 循环 变量 变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中 ...
- File类的使用
java.io.File 类用于表示文件(目录) File类只用于表示文件(目录)的信息(名称.大小等),不能用于文件内容的访问 file类常用的api package com.zhb.java; i ...
- Hacker(七)----黑客常用术语和DOS命令
掌握基本的黑客术语和DOS命令是一名黑客最基本的技能,黑客术语能够实现自己和其他人之间的正常交流.DOS命令就是DOS操作系统的命令,它是一种面向磁盘的操作命令.黑客在入侵目标主机的过程中经常会使用这 ...
- NO.14 两个div并排,左边为绝对宽度,右边为相对宽度
两个div并排,左边为绝对宽度,右边为相对宽度,这个问题,我也经常遇到,我一般的处理方法是将最大的容器padding-left固定宽度,左边的固定宽度的一块position:absolute,然后ri ...