bzoj 1040 骑士
题目大意:
每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己)和他自己的战斗力
从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况)
并且,使得这支骑士军团最具有战斗力
思路:
又题目可知
把图连出来之后是一些树上带一个或不带环
对于没有环的直接像上司的舞会一样dp即可
对于有环的把环拆开
把分裂的点 分别做为根 另一个定为不能取 dp两次
最后把每个(环套)树的答案相加即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 1001001 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); 19 return x*f; 20 } 21 int n,fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt; 22 int val[MAXN],vis[MAXN],t1,t2,ok[MAXN<<1],ban; 23 ll dp[MAXN][2],res,ans; 24 void add(int u,int v) {nxt[cnt]=fst[u],fst[u]=cnt,to[cnt++]=v;} 25 void dfs(int x,int fa) 26 { 27 vis[x]=1; 28 for(int i=fst[x];i!=-1;i=nxt[i]) 29 { 30 if(to[i]==fa) continue; 31 if(vis[to[i]]) 32 { 33 t1=x,t2=to[i],ok[i]=ok[i^1]=1; 34 return ; 35 } 36 dfs(to[i],x); 37 } 38 } 39 void Dp(int x,int fa) 40 { 41 vis[x]=1; 42 if(x==ban) dp[x][1]=0; 43 else dp[x][1]=val[x]; 44 dp[x][0]=0; 45 for(int i=fst[x];i!=-1;i=nxt[i]) 46 if(to[i]!=fa&&!ok[i]) 47 { 48 Dp(to[i],x); 49 dp[x][1]+=dp[to[i]][0],dp[x][0]+=max(dp[to[i]][1],dp[to[i]][0]); 50 } 51 } 52 int main() 53 { 54 memset(fst,0xff,sizeof(fst)); 55 n=read();int a; 56 for(int i=1;i<=n;i++) {val[i]=read(),a=read();add(i,a);add(a,i);} 57 for(int i=1;i<=n;i++) 58 if(!vis[i]) 59 { 60 t1=t2=res=0; 61 dfs(i,0); 62 ban=t2;Dp(t1,0); 63 res=max(dp[t1][0],dp[t1][1]); 64 ban=t1;Dp(t2,0); 65 ans+=max(res,max(dp[t2][0],dp[t2][1])); 66 } 67 printf("%lld",ans); 68 }