zoukankan      html  css  js  c++  java
  • 【CF671D】Roads in Yusland(贪心,左偏树)

    【CF671D】Roads in Yusland(贪心,左偏树)

    题面

    洛谷
    CF

    题解

    无解的情况随便怎么搞搞提前处理掉。
    通过严密(大雾)地推导后,发现问题可以转化成这个问题:

    给定一棵树,每条边可以被标记若干次,有若干个限制,每次限制一条链上所有边被覆盖的总次数不能超过一个给定值,现在要最大化边被覆盖的总次数。

    不难发现转化出来的问题可以贪心来做,即一条边在满足所有限制的情况下,选择其能够被覆盖的最多次数一定不会更差,所以只要能覆盖就覆盖。
    那么拿左偏树进行堆的合并就可以很容易的从下往上维护这个操作。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define ll long long
    #define MAX 300300
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    struct Line{int v,next;}e[MAX<<1];
    int h[MAX],cnt=1;
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    int n,m;ll ans;
    int x[MAX],y[MAX],z[MAX],c[MAX],dep[MAX];
    void pre(int u,int ff)
    {
    	dep[u]=dep[ff]+1;
    	for(int i=h[u];i;i=e[i].next)
    		if(e[i].v!=ff)
    			pre(e[i].v,u),c[u]+=c[e[i].v];
    }
    struct Node{int ls,rs,dep,v,ed,tag;}t[MAX];
    int rt[MAX];
    void pushdown(int r)
    {
    	if(!t[r].tag)return;int w=t[r].tag;
    	if(t[r].ls)t[t[r].ls].v+=w,t[t[r].ls].tag+=w;
    	if(t[r].rs)t[t[r].rs].v+=w,t[t[r].rs].tag+=w;
    	t[r].tag=0;
    }
    int Merge(int r1,int r2)
    {
    	if(!r1||!r2)return r1|r2;
    	pushdown(r1);pushdown(r2);
    	if(t[r1].v>t[r2].v)swap(r1,r2);
    	t[r1].rs=Merge(t[r1].rs,r2);
    	if(t[t[r1].ls].dep<t[t[r1].rs].dep)swap(t[r1].ls,t[r1].rs);
    	t[r1].dep=t[t[r1].rs].dep+1;
    	return r1;
    }
    void Solve(int u,int ff)
    {
    	for(int i=h[u];i;i=e[i].next)
    		if(e[i].v!=ff)
    			Solve(e[i].v,u),
    				rt[u]=Merge(rt[e[i].v],rt[u]);
    	if(u==1)return;
    	while(dep[t[rt[u]].ed]>=dep[u])rt[u]=Merge(t[rt[u]].ls,t[rt[u]].rs);
    	int w=t[rt[u]].v;
    	ans+=w;t[rt[u]].v-=w,t[rt[u]].tag-=w;
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
    	for(int i=1;i<=m;++i)x[i]=read(),y[i]=read(),z[i]=read();
    	for(int i=1;i<=m;++i)c[x[i]]+=1,c[y[i]]-=1;
    	pre(1,0);
    	for(int i=2;i<=n;++i)if(c[i]<=0){puts("-1");return 0;}
    	for(int i=1;i<=m;++i)t[i]=(Node){0,0,0,z[i],y[i],0},rt[x[i]]=Merge(rt[x[i]],i);
    	Solve(1,0);
    	printf("%I64d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    valgrind内存检测
    uosdeepin商店下载的软件deb包位置
    jmeter中获取到token,又因为现在都是JWT的所以需要添加Bearer 和获取到的token进行拼接
    jmeter json提取器
    jmeter命令行启动
    linux 中把文件内容变成空,不删除文件
    94--分布式事务五-Seata AT模式-Spring Cloud微服务案例(添加AT事务)
    94--Docker(概念/镜像操作/数据管理/网络/互联/构建镜像)
    93--分布式事务四-Seata AT模式-Spring Cloud微服务案例(无事务)
    93--分布式事务二-Seata AT 模式
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10479304.html
Copyright © 2011-2022 走看看