zoukankan      html  css  js  c++  java
  • [八省联考 2018]林克卡特树

    题意:求一个凸函数的最优解。。。

    思路:

    好吧在题意里已经说出来了。

    对于被卡斜率的,只能\(orz\)了。。。

    其实据说还有\(12s\)评测这种操作,对不起我省\(5s\)

    好吧不废话了,看看应该怎么做。

    暴力的话直接记\(dp[i][j][0->2]\)表示当前做到第 \(i\) 棵子树用了$ j$ 条链并且当前点有\(0->2\)条出边,转移也好想。。。

    正解的话。。。就是二分斜率。。

    我们记\(f[i][0->2]\)表示做到$ i $子树并且出边是\(0->2\)个。

    然后差分,发现单调凸性质,在函数上二分最优解即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn = 600010;
    inline int read()
    {
    	int q=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-') f=-1;ch=getchar();
    	}
    	while(isdigit(ch)){
    		q=q*10+ch-'0';ch=getchar();
    	}
    	return q*f;
    }
    
    struct node
    {
    	int x;int y;
    	inline void max(int a,int b){
    		if(x < a||(x == a && y > b)) x = a,y = b;
    	}	
    }fp[maxn][3];
    node dp[maxn];
    node fg[3];
    node tmp;
    int n,m,k,q;
    
    int cnt;
    struct edge
    {
    	int to;
    	int nxt;
    	int w;
    }e[maxn<<4];
    int head[maxn];
    inline void add(int u,int v,int w){
    	e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;e[cnt].w=w;return;
    }
    const int inf = 0x7fffffff;
    inline void dfs(int x,int f){
    	fp[x][0].x=0;fp[x][0].y=0;
    	//fp[x][0]=(0,0);
    	fp[x][1].x=-q;fp[x][1].y=1;
    	fp[x][2].x=-inf;fp[x][2].y=0;
    	for(int i = head[x];i;i=e[i].nxt){
    		int y=e[i].to;
    		if(y != f){
    			dfs(y,x);
    			for(int j = 0;j < 3; ++j){
    				fg[j]=fp[x][j];
    			}
    			tmp = dp[y];
    			for(int j = 0;j < 3; ++j){
    				fp[x][j].max(fg[j].x+tmp.x,fg[j].y+tmp.y);
    			}
    			fp[x][1].max(fg[0].x+fp[y][1].x+e[i].w,fg[0].y+fp[y][1].y);
    			fp[x][2].max(fg[1].x+fp[y][1].x+e[i].w+q,fg[1].y+fp[y][1].y-1);
    		}
    	}
    	dp[x]=fp[x][0];
    	for(int i = 1;i < 3; ++i){
    		dp[x].max(fp[x][i].x,fp[x][i].y);
    	}
    	return;
    }
    int ans;
    signed main()
    {
    	n=read(),m=read();
    	++m;
    	for(int i = 1;i < n; ++i){
    		int u=read(),v=read(),w=read();
    		add(u,v,w);add(v,u,w);
    	}
    	int l=-inf,r=inf;
    	while(l <= r){
    		q=(l + r)>>1;
    		dfs(1,0);
    		if(dp[1].y <= m){
    			ans = q;
    			r = q - 1;
    		}
    		else l = q + 1;
    	}
    	q = ans;
    	dfs(1,0);
    	cout<<dp[1].x+m*q<<endl;
    	return 0;
    }
    
  • 相关阅读:
    解决adb的"more than one device and emulator"错误
    Swoole实现简单的http服务器
    Unity实现物体位置变换
    Unity实现放大或缩小某个物体
    如何使用WEBSOCKET实现前后端通信
    实体类接收Date类型
    easyExce输出Excel只有表头没有数据问题解决
    报餐统计
    使用 EasyExcel 写Excel数据(表头动态)
    bladex分页
  • 原文地址:https://www.cnblogs.com/akoasm/p/9444066.html
Copyright © 2011-2022 走看看