• bzoj 4472 salesman


    Written with StackEdit.

    Description

    某售货员小(T) 要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇 之间都只有唯一的可能经过其它城镇的路线。 小(T) 可以准确地估计出在每个城镇停留的净收 益。这些净收益可能是负数,即推销商品的利润抵不上花费。由于交通不便,小(T) 经过每个城镇都需要停留,在每个城镇的停留次数与在该地的净收益无关,因为很多费用不是计次收取的,而每个城镇对小T的商品需求也是相对固定的,停留一次后就饱和了。每个城镇为了强化治安,对外地人的最多停留次数有严格的规定。请你帮小(T) 设计一个收益最大的巡回方案,即从家乡出发,在经过的每个城镇停留,最后回到家乡的旅行方案。你的程序只需输出最大收益,以及最优方案是否唯一。方案并不包括路线的细节,方案相同的标准是选择经过并停留的城镇是否相同。因为取消巡回也是一种方案,因此最大收益不会是负数。小(T) 在家乡净收益是零,因为在家乡是本地人,家乡对小(T) 当然没有停留次数的限制。

    Input

    输入的第一行是一个正整数(n),((5<=n<=100000)),表示城镇数目。城镇以(1)(n)的数命名。小(T) 的家乡命 名为(1)
    第二行和第三行都包含以空格隔开的(n-1)个整数,第二行的第(i)个数表示在城镇(i+1)停留的净收益。
    第三行的第(i)个数表示城镇(i+1)规定的最大停留次数。所有的最大
    停留次数都不小于(2)
    接下来的(n-1)行每行两个(1)(n)的正整数(x,y),之间以一个空格隔开,表示(x,y)之间有一条不经过其它城镇的双向道路。输入数据保证所有城镇是连通的。

    Output

    输出有两行,第一行包含一个自然数,表示巡回旅行的最大收益。
    如果该方案唯一,在 第二行输出“solution is unique”,否则在第二行输出“solution is not unique”。

    Sample Input

    9
    -3 -4 2 4 -2 3 4 6
    4 4 2 2 2 2 2 2
    1 2
    1 3
    1 4
    2 5
    2 6
    3 7
    4 8
    4 9

    Sample Output

    9
    solution is unique
    //最佳路线包括城镇 1,2, 4, 5, 9。

    Solution

    • 树形dp的入门题.(确定是省选的题?)
    • 注意到次数限制(t)其实就是到达该点后,最多再进入它的(t-1)颗子树.
    • (f[i])表示从(i)节点向下方走,最后回到(i)的最大收益.
    • (g[i])表示取得(f[i])这个最大收益的方案是否唯一.
    • 考虑状态转移,若记每个点的收益为(w),停留次数为(t).
    • (f[i])就为(w[i])加上最多(t-1)个子树的收益.将儿子按照(f)排序即可.
    • (g[i])在满足以下(3)中情况中任意一种时为(0):
      • 某个取得的儿子(f)值为(0).(我们可以选择不取它).
      • 某个取得的儿子(g)值为(0).(我们在这颗子树中有不同的路径)
      • 下个未选的儿子(如果有)和最后选择的儿子(f)值相同.(可以替换).
    • 其他时候(g[i])均为(1).
    • 答案即为(f[1],g[1]).
    #include<bits/stdc++.h>
    #define inf 0x7fffffff
    #define yes "solution is unique"
    #define no "solution is not unique"
    using namespace std;
    typedef long long LoveLive;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    const int MAXN=1e5+10;
    int cnt=0,head[MAXN];
    int to[MAXN<<1],nx[MAXN<<1];
    inline void add(int u,int v)
    {
    	++cnt;
    	to[cnt]=v;
    	nx[cnt]=head[u];
    	head[u]=cnt;
    }
    int n;
    int t[MAXN],w[MAXN];
    int f[MAXN],g[MAXN];
    int cmp(const int &x,const int &y)
    {
    	return f[x]>f[y];
    }
    // 1 stands for unique
    // 0 stands for not unique
    void dfs(int u,int fa)
    {
    	f[u]=w[u];
    	g[u]=1;
    	vector<int> sons;
    	for(int i=head[u];i;i=nx[i])
    		{
    			int v=to[i];
    			if(v==fa)
    				continue;
    			dfs(v,u);
    			sons.push_back(v);
    		}
    	sort(sons.begin(),sons.end(),cmp);
    	int siz=sons.size();
    	int lim=min(t[u],siz);
    	int sel=0;
    	for(int i=0;i<lim;++i)
    		{
    			if(f[sons[i]]<0)//若f值开始为负,后面都不能选择
    				break;
    			f[u]+=f[sons[i]];
    			++sel;
    			if(f[sons[i]]==0)
    				g[u]=0;
    			if(g[sons[i]]==0)
    				g[u]=0;
    		}
    	if(sel<siz && f[sons[sel-1]]==f[sons[sel]])
    		g[u]=0;
    }
    int main()
    {
    	n=read();
    	for(int i=2;i<=n;++i)
    		w[i]=read();
    	for(int i=2;i<=n;++i)
    		t[i]=read(),--t[i];//t[i]表示i最多能选取多少个子树 
    	for(int i=1;i<n;++i)
    		{
    			int u=read(),v=read();
    			add(u,v);
    			add(v,u);
    		}
    	w[1]=0;
    	t[1]=inf;
    	dfs(1,0);
    	printf("%d
    %s
    ",f[1],g[1]?yes:no);
    	return 0;
    }
    
  • 相关阅读:
    Eclipse和MyEclipse常出现的错误总结
    JS中的showModelDialog详解和实例
    form中的action,submit="return save()"以及ajax提交方法
    清除上传文件input标签中type="file"的value值
    上传文件时并顺便将文件压缩时出现文件名乱码以及文件内容乱码解决方案
    python 知识
    centos 安装docker
    docker 配置国内镜像
    git 操作命令
    react build dist发布nginx时的配置
  • 原文地址:https://www.cnblogs.com/jklover/p/10025012.html
Copyright © 2020-2023  润新知