思路:看到这题,就感觉是一道很熟悉的题目:

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的更多相关文章

  1. BZOJ NOI十连测 第二测 T2

    思路:20%可以搜索.. #include<algorithm> #include<cstdio> #include<cmath> #include<cstr ...

  2. BZOJ NOI十连测 第一测 T1

    思路:首先考虑t=1的情况,t等于1,那么所有位置的颜色相同,我们不用考虑概率的问题,那么,k+d*x在模d下都相等,我们考虑预处理一个数组s[i][j],代表d为i,起始位置为j的等差数列的和,这个 ...

  3. BZOJ NOI十连测 第二测 T1

    出题人居然是个哲学家.. 26%的程序,太SB了...本来我的想法也是二分+贪心,但是贪心是个怪怪的SX贪心.. #include<algorithm> #include<cstdi ...

  4. 痞子衡嵌入式:测一测i.MXRT1170 Raw NAND启动时间(从POR到进App的Reset_Handler)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 Raw NAND启动时间. 关于i.MXRT1170这颗划时代的MCU,痞子衡去年10月在其刚发布的时候, ...

  5. 「NOI十联测」深邃

    「NOI十联测」深邃 要使得最大的连通块最小,显然先二分答案. 先固定1结点为根. 对于一个果实,显然是先处理子树中未分配的点,再向外延伸. 每个结点记录一个\(si[]\),表示子树中未分配的点数, ...

  6. 「NOI十联测」奥义商店

    「NOI十联测」奥义商店 若lzz想花费最少的钱,那么显然要选择数目较少的颜色. 先考虑暴力的写法. 每次向两边统计,每个物品要求被买的概率可以由上一个物品推出. now=1;//now 被买概率 M ...

  7. 「NOI十联测」黑暗

    「NOI十联测」黑暗 \(n\) 个点的无向图,每条边都可能存在,一个图的权值是连通块个数的 \(m\) 次方,求所有可能的图的权值和.(n≤30000,m≤15) 令\(ans[n][m]\)为n个 ...

  8. NOI十连测 第五测 T2

    思路:考虑建立可持久化线段树,第一层维护的是i这个位置的next位置,第二层,维护的是接下来走这个字符会到哪个节点. 感觉很巧妙啊,不愧是Claris #include<algorithm> ...

  9. NOI十连测 第四测 T2

    思路:线段树套可持久化treap,可持久化treap我还是第一次听说.. 改题的时候没看数据范围..乱开数组T_T #include<algorithm> #include<cstd ...

随机推荐

  1. Qt带进度条的启动界面(继承QSplashScreen,然后使用定时器)

    通过继承QSplashScreen类,得到CMySplashScreen类,然后在CMySplashScreen中定义QProgressBar变量,该变量以CMySplashScreen为父类,这样就 ...

  2. pl/sql执行动态sql

    SQL> declare             msql varchar2(200);    begin    loop    msql := 'select * from bfw_test' ...

  3. UML--一些图

    通过UML来表示汽车,简洁明了. 统一建模语言--UML. 参与者Actor,参与者代表了现实世界的人.人. 用例use case,就是参与者要做什么并且获得什么.事. 业务场景,用例场景.规则. 业 ...

  4. cf446A DZY Loves Sequences

    A. DZY Loves Sequences time limit per test 1 second memory limit per test 256 megabytes input standa ...

  5. unix c 09

    IPC - 进程间通信   文件/信号/管道/共享内存/消息队列/信号量集/网络   XSI IPC (共享内存.消息队列和信号量集)   使用方式 非常的类似. 共享内存的使用步骤:     1 生 ...

  6. 最详细的 HTTPS 科普扫盲帖

    为什么需要https HTTP是明文传输的,也就意味着,介于发送端.接收端中间的任意节点都可以知道你们传输的内容是什么.这些节点可能是路由器.代理等. 举个最常见的例子,用户登陆.用户输入账号,密码, ...

  7. java并发编程--Executor框架(一)

    摘要:        Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程 ...

  8. Spring (二) OOP V.S AOP

    介绍 这是两种不同的编程思想就好比初中数学中学习的横纵坐标,一种是横向的一种是纵向,OOP是代表X轴而AOP代表Y轴,如下图: 数学几乎可以解释生活中所有的现象,无论是物体运动还是静止,也可以通过数学 ...

  9. jquery使用load开展局部刷新没有效果

    jquery使用load开展局部刷新没有效果   jquery使用load进行局部刷新没有效果我的代码 <html><head><meta charset="u ...

  10. [J2EE框架][Debug]

    注意xml头部问题 比如在xx-servlet中注意: <mvc:annotation-driven/> <context:component-scan base-package=& ...