传送门
又一个没有上司的舞会
这个dp有环 妈妈怎么办啊
要不...环上随便断一条边?
然后最后选的时候分别取两个根节点不选的情况的最大值
几个要点:
1.图可能是多个环套树 要循环走完
2.不能只记录顶点 因为如果有重边的话会把二元环筛掉
3.位运算优先级... 要写成(i^1)==cntline
Time cost inf
这题从上周就开始D
一度放弃 今天想整一下以前做过的所有题然后就
就写出来啦!!(开心)
Code:
(边界写的比较奇怪 是Debug的时候被吓怕了)
1 #include2 #include 3 #include 4 #include 5 #include 6 #define ms(a,b) memset(a,b,sizeof a) 7 #define inf 2147483647 8 #define rep(i,a,n) for(int i = a;i <= n;i++) 9 #define per(i,n,a) for(int i = n;i >= a;i--) 10 using namespace std; 11 typedef long long ll; 12 int read() { 13 int as = 0,fu = 1; 14 char c = getchar(); 15 while(c<'0'||c>'9') { 16 if(c == '-') fu = -1; 17 c = getchar(); 18 } 19 while(c<='9'&&c>='0') { 20 as = as * 10 + c - '0'; 21 c = getchar(); 22 } 23 return as * fu; 24 } 25 const int N = 1000005; 26 //head 27 int n; 28 int head[N],nxt[N<<1],mo[N<<1],cnt = -1; 29 void _add(int x,int y) { 30 mo[++cnt] = y; 31 nxt[cnt] = head[x]; 32 head[x] = cnt; 33 } 34 void add(int x,int y) {if(x^y)_add(x,y),_add(y,x);} 35 36 int rt1,rt2,Cntline; 37 bool vis[N]; 38 void dfs(int x,int f) { 39 vis[x] = 1; 40 for(int i = head[x];~i;i = nxt[i]) { 41 int sn = mo[i]; 42 if(sn == f) continue; 43 if(!vis[sn]) dfs(sn,x); 44 else { 45 rt1 = x,rt2 = sn; 46 Cntline = i; 47 } 48 } 49 } 50 51 int v[N]; 52 ll dp[N][2]; 53 void Dp(int x,int f) { 54 dp[x][0] = 0,dp[x][1] = v[x]; 55 for(int i = head[x];~i;i = nxt[i]) { 56 int sn = mo[i]; 57 if(sn == f) continue; 58 if(i == Cntline || ((i ^ 1) == Cntline)) continue; 59 // printf("%d->%d\n",x,sn); 60 Dp(sn,x); 61 dp[x][0] += max(dp[sn][0],dp[sn][1]); 62 dp[x][1] += dp[sn][0]; 63 } 64 } 65 66 int main() { 67 ms(head,-1); 68 n = read(); 69 rep(i,1,n) { 70 v[i] = read(); 71 add(i,read()); 72 } 73 ll ans = 0,maxx; 74 rep(i,1,n) { 75 maxx = 0; 76 if(vis[i]) continue; 77 rt1 = rt2 = Cntline = -2; 78 dfs(i,-1); 79 // printf("%d %d %d\n",rt1,rt2,Cntline); 80 Dp(rt1,rt1),maxx = dp[rt1][0]; 81 // printf("#%d\n",maxx); 82 Dp(rt2,rt2),maxx = max(maxx,dp[rt2][0]); 83 // printf("#%d\n",maxx); 84 ans += maxx; 85 } 86 printf("%lld\n",ans); 87 return 0; 88 }