zoukankan      html  css  js  c++  java
  • [洛谷P1352][codevs1380]没有上司的舞会

    题目大意:某大学有N个职员,编号为1~N。他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但如果某个职员的上司来参加舞会了,那么这个职员就不肯参加舞会了。求最大的快乐指数。

    解题思路:经典的树形dp。我们设f[i][0]表示i参加时能获得的最大快乐指数,f[i][1]表示i不参加时能获得的最大快乐指数。

    那么如果i参加,则他的下属一定不能参加,就在他参加获得的快乐指数上加上他所有下属不参加时的最大快乐指数(f[p][1],p是i的某个下属)

    如果i不参加,他的下属可以参加也可以不参加,那么对于每个下属,我们把他参加和不参加时的快乐指数的较大值($max(f[p][1],f[p][0])$)加到f[i][1]中即可。

    最后的答案为$max(f[root][1],f[root][0])$,root表示“校长”。

    时间复杂度$O(n)$。

    C++ Code:

    #include<cstdio>
    #include"cctype"
    #include<vector>
    using namespace std;
    #define C c=getchar()
    int boss[6050],a[6050],n,f[6050][2];
    //f[i][0]表示i参加时能获得的最大快乐指数,f[i][1]表示i不参加时能获得的最大快乐指数。
    vector<int> e[6050];
    inline int readint(){
    	char C;
    	bool b=false;
    	while(!isdigit(c))b=c=='-',C;
    	int p=0;
    	while(isdigit(c))
    	p=(p<<3)+(p<<1)+c-'0',C;
    	if(b)p=-p;
    	return p;
    }
    void dp(int t){
    	f[t][0]=a[t];
    	f[t][1]=0;
    	for(int i=0;i<e[t].size();++i){
    		int to=e[t][i];
    		dp(to);
    		f[t][0]+=f[to][1];
    		f[t][1]+=(f[to][0]<f[to][1])?(f[to][1]):(f[to][0]);
    	}
    }
    int main(){
    	n=readint();
    	int x,y;
    	for(int i=1;i<=n;++i)a[i]=readint();
    	while((x=readint())&&(y=readint())){
    		boss[x]=y;
    		e[y].push_back(x);
    	}
    	for(int i=1;i<=n;++i)
    	if(!boss[i]){//寻找“校长”。 
    		dp(i);
    		printf("%d
    ",(f[i][0]<f[i][1])?f[i][1]:f[i][0]);
    		return 0;
    	}
    }
    
  • 相关阅读:
    荷兰国旗问题
    读取文件中数据到数组
    从五个球中选出3个枚举的简单运用
    搜索算法总结
    匿名对象
    欧几里得距离C++代码实现
    用递归法吧字符串S倒序
    利用系统来完成十进制,十六进制,八进制的转换
    DBHelper 使用的是存储过程
    DBHelper的一个小例子
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7295740.html
Copyright © 2011-2022 走看看