bzoj 1040: [ZJOI2008]骑士 環套樹DP

时间:2014-10-03 01:46:03   收藏:0   阅读:336

1040: [ZJOI2008]骑士

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1755  Solved: 690
[Submit][Status]

Description

Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。

Input

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

Output

应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。

Sample Input

3
10 2
20 3
30 1

Sample Output

30

HINT

 

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

 

Source

   ╮(╯▽╰)╭ 網上說什麼外向樹內向樹,完全不懂,說白了,這道題就是一個環套樹DP,由於每個人只貢獻一條邊,所以最終圖的結構只會是一系列包含一個環的聯通快,在這些聯通塊上分別做環套樹DP就行了。

  這道題環套樹DP非常簡單,直接隨機選環上一條邊刪掉,然後特殊處理刪掉邊的兩個端點,使之不被選擇,然後在樹上DP即可。

  這是我第一次編環套樹。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#define MAXN 1100000
#define MAXV MAXN*2
#define MAXE MAXV*2
#define INF 0x3f3f3f3f
#define INFL 0x00003f3f3f3f3f3fLL
typedef long long qword;
inline int nextInt()
{
        char ch;
        int x=0;
        bool flag=false;
        do
                ch=getchar(),flag=(ch==-)?true:flag;
        while(ch<0||ch>9);
        do x=x*10+ch-0;
        while (ch=getchar(),ch<=9 && ch>=0);
        return x*(flag?-1:1);
}

int n,m;
int e[MAXN][3];
struct Edge
{
        int np;
        Edge *next;
}E[MAXE],*V[MAXV];
int tope=-1;
void addedge(int x,int y)
{
        E[++tope].np=y;
        E[tope].next=V[x];
        V[x]=&E[tope];
}
int uf[MAXN];
int get_fa(int now)
{
        return (now==uf[now])?now:(uf[now]=get_fa(uf[now]));
}
bool comb(int x,int y)
{
        x=get_fa(x);
        y=get_fa(y);
        if (x==y)return false;
        uf[x]=y;
        return true;
}
int roof[MAXN],topr=-1;
int state[MAXN];
int ptr[MAXN];
int v[MAXN];
pair<qword,qword> dfs(int now,int f)
{
        pair<qword,qword> ret,t;
        Edge *ne;
        ret=make_pair(v[now],0);
        for (ne=V[now];ne;ne=ne->next)
        {
                if (ne->np==f)continue;
                t=dfs(ne->np,now);
                ret.second+=max(t.first,t.second);
                ret.first+=t.second;
        }
        if (state[now])ret.first=-INFL;
        return ret;
}
int main()
{        int i,j,k;
        int x,y,z;
        qword ans=0;
        scanf("%d",&n);
        memset(ptr,-1,sizeof(ptr));
        for (i=0;i<=n;i++)uf[i]=i;
        for (i=0;i<n;i++)
        {
                scanf("%d%d",&v[i+1],&e[i][1]);
                e[i][0]=i+1;
                if (!comb(e[i][0],e[i][1]))
                {
                        roof[++topr]=e[i][0];
                        e[i][2]=true;
                        ptr[e[i][0]]=e[i][1];
                }else
                {
                        addedge(e[i][0],e[i][1]);
                        addedge(e[i][1],e[i][0]);
                }
        }
        for (i=0;i<=topr;i++)
        {
                state[get_fa(roof[i])]=true;
        }
        for (i=1;i<=n;i++)
        {
                if (!state[get_fa(i)])
                {
                        state[get_fa(i)]=true;
                        roof[++topr]=get_fa(i);
                }
        }
        memset(state,0,sizeof(state));
        pair<qword,qword> pr;
        qword t;
        for (i=0;i<=topr;i++)
        {
                if (ptr[roof[i]]==-1)
                {
                        pr=dfs(roof[i],roof[i]);
                        ans+=max(pr.first,pr.second);
                }else
                {
                        //state[roof[i]]=true;
                        state[ptr[roof[i]]]=true;
                        pr=dfs(roof[i],roof[i]);
                        t=max(pr.first,pr.second);
                        state[ptr[roof[i]]]=false;
                        pr=dfs(roof[i],roof[j]);
                        t=max(t,pr.second);
                        ans+=t;
                }
        }
        printf(LL"\n",ans);
        return 0;
}

 

 
评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!