• [luogu2607 ZJOI2008] 骑士 (树形dp)


    题目描述

    Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。

    最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。

    骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。

    战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。

    为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。

    输入输出格式

    输入格式:
    输入文件knight.in第一行包含一个正整数N,描述骑士团的人数。

    接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。

    输出格式:
    输出文件knight.out应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。

    输入输出样例

    输入样例#1:
    3
    10 2
    20 3
    30 1
    输出样例#1:
    30

    说明

    对于30%的测试数据,满足N ≤ 10;

    对于60%的测试数据,满足N ≤ 100;

    对于80%的测试数据,满足N ≤ 10 000。

    对于100%的测试数据,满足N ≤ 1 000 000,每名骑士的战斗力都是不大于 1 000 000的正整数。

    做法

    “我厌恶的人的厌恶的人不是我厌恶的人”
    所以这个题与舞会很像不过会有环(无自环)
    对于环如何处理呢?
    我们在环上随意选取两个点 由题意可知他们是不能同时出现的 并且题中权值为点权
    那我们只需放弃这条边然后各自跑一个舞会即可

    code:

    //By Menteur_Hxy
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    #include <cmath>
    #include <vector>
    #include <queue>
    #define M(a,b) memset(a,(b),sizeof(a))
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    #define LL long long
    using namespace std;
    
    inline LL rd() {
        LL x=0,fla=1; char c=' ';
        while(c>'9'|| c<'0') {if(c=='-') fla=-fla; c=getchar();}
        while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
        return x*fla;
    }
    
    inline void out(LL x){
        int a[25],wei=0;
        if(x<0) putchar('-'),x=-x;
        for(;x;x/=10) a[++wei]=x%10;
        if(wei==0){ puts("0"); return;}
        for(int j=wei;j>=1;--j) putchar('0'+a[j]);
        putchar('
    ');
    }
    
    const int N=1000010;
    const int INF=0x3f3f3f3f;
    int n,m,cnt;
    int head[N],fa[N],v[N],ra[N],rb[N];
    int to[N<<1],nex[N<<1];
    LL f[N],g[N];
    
    struct edges{
        int nex,to,dis;
    }e[N];
    
    int get(int x) {
    	return fa[x]==x?x:fa[x]=get(fa[x]);
    }
    
    void add(int a,int b) {
    	nex[++cnt]=head[a];
    	to[cnt]=b;
    	head[a]=cnt;
    }
    
    void dfs(int x,int pre) {
    	f[x]=v[x],g[x]=0;
    	for(int i=head[x];i;i=nex[i]) {
    		if(to[i]==pre) continue;
    		dfs(to[i],x);
    		g[x]+=max(f[to[i]],g[to[i]]);
    		f[x]+=g[to[i]];
    	}
    }
    
    int main() {
        n=rd();
    	F(i,1,n) fa[i]=i;
    	F(i,1,n) {
    		v[i]=rd(); int b=rd();
    		if(get(i)!=get(b)) {
    			add(i,b),add(b,i);
    			fa[fa[i]]=fa[b];
    		}
    		else ra[++m]=i,rb[m]=b;
    	}
    	LL ans=0;
    	F(i,1,m) { LL tp;
    		dfs(ra[i],0),tp=g[ra[i]];
    		dfs(rb[i],0),tp=max(tp,g[rb[i]]);
    		ans+=tp;
    	}
    	out(ans);
    	return 0;
    }  
    
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    3.13作业 制作网页布局
    3.11 框架和样式表
    表单
    3.8学习记录
    第一次作业
    数据库增删改查
    数据库三大范式
    数据库中的时间戳
    数据库的主键与外键
    登录页面
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9148022.html
Copyright © 2020-2023  润新知