Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。
第一行包含一个正整数N,描述骑士团的人数。接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。
应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。
对于100%的测试数据,满足N ≤ 1 000 000,每名骑士的战斗力都是不大于 1 000 000的正整数。
╮(╯▽╰)╭ 網上說什麼外向樹內向樹,完全不懂,說白了,這道題就是一個環套樹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;
}