• 【2020.11.30提高组模拟】删边(delete) 题解


    T1 删边(delete)

    题意

    给一棵树删边,每次删的代价为这条边所连的两个点的子树中最大点权值。

    求删光的最小代价。

    n≤100000

    做法

    O(nlogn)

    详见hash大犇的博客

    O(n)

    先选权值最大的点,那么它的贡献是 w[i]*degree[i]
    ,那么对于剩下几个连通块中权值最大的点,它们的贡献是 w[i]*(degree[i]+1),首先与他相连的边肯定有一端要选它,还有整个连通块和权值最大的点相连的边也有一端要选它(除了它和权值最大的点相连不用+1

    但是这样太麻烦了,而且时间复杂度太大过不去,于是发现每个贡献都有已知的w[i],那么只用求degree[i],然后就可以尝试连一些新的边:从选权值最大的点开始,对于与它相连的每个连通块的边连到那个连通块的权值最大的点,这样建出的图degree[i]就是与点i相连的边的度数

    这样时间复杂度还是过不去,再想亿想,求degree[i]又不一定要建出具体的图,建图不写出来,直接求degree[i]不就行了,本文完

    以权值最大的点为根节点,对于每个父亲节点,如果他的某个儿子权值比它大,
    那就把那个儿子的整颗子树移上去,把它作为自己的父亲节点,于是它的孙子成了它的兄弟,如果有很多个这样的儿子,那就把更大权值的儿子作为更小权值儿子的父亲

    分析完了,怎么写呢?不用写

    其实总的就是对于那种父亲节点,那样的儿子结点多了个儿子,而它自己少了个儿子,所以in[x]++,in[fa[x]]--就完事了

    #include<bits/stdc++.h>
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define int long long
    #define re register
    #define mod 998244353
    #define inf 0x3f3f3f3f
    using namespace std;
    const int N=100005;
    int n,ma,num,ans;
    int w[N],s[N];
    bool v[N];
    vector<int> a[N];
    template <class T> inline void read(T &x){
    	x=0;int g=1; char s=getchar();
    	for (;s>'9'||s<'0';s=getchar())	if (s=='-') g=-1;
    	for (;s<='9'&&s>='0';s=getchar()) x=(x<<1)+(x<<3)+(s^48);
    	x*=g;
    }
    queue <int> q;
    void bfs()
    {
    	q.push(num);
    	v[num]=1;
    	while(q.size())
    	{
    		int x=q.front();q.pop();
    		for (re int i=0;i<a[x].size();i++)
    		if (!v[a[x][i]])
    		{
    			int y=a[x][i];
    			v[y]=1;
    			if (w[y]>w[x]) s[x]--,s[y]++;
    			q.push(y);
    		}	
    	}
    }
    signed main()
    {
    	re int i,j,x,y,z;
    	freopen("delete.in","r",stdin);freopen("delete.out","w",stdout);
    	read(n);
    	for (i=1;i<=n;i++) 
    		{read(w[i]);if (w[i]>ma) ma=w[i],num=i;}
    	for (i=1;i<n;i++)
    	{
    		read(x);read(y);
    		a[x].push_back(y);
    		a[y].push_back(x);
    	}
    	for (i=1;i<=n;i++) s[i]=a[i].size();
    	bfs();
    	for (i=1;i<=n;i++) ans+=w[i]*s[i];
    	printf("%lld",ans);
    	
    	return 0;
    }          
    
  • 相关阅读:
    用python实现简单的调度场算法
    数据结构顺序表python
    数据结构顺序表C
    python绘制5角形,6角星方法
    TsinghuaX+00740043_2X C++程序设计进阶 C7-3
    Struts2开发环境搭建,及一个简单登录功能实例
    Javascript进度条
    java.util.Date与java.sql.Date
    Error while performing database login with the sqljdbc driver:Unable to create connection. Check your URL.
    java.sql.SQLException: [Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
  • 原文地址:https://www.cnblogs.com/Ritalc/p/14061147.html
Copyright © 2020-2023  润新知