zoukankan      html  css  js  c++  java
  • BZOJ2466: [中山市选2009]树

    BZOJ2466: [中山市选2009]树

    https://lydsy.com/JudgeOnline/problem.php?id=2466

    分析:

    • 半年前写的高斯消元调不出来了。
    • 现在来看这道题不是沙茶树形dp?
    • (f[x][0/1][0/1])表示(x)的子树不包含(x)都亮了,(x)按没按,(x)亮不亮。
    • 然后转移即可。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <vector>
    #include <iostream>
    #include <cmath>
    #include <set>
    using namespace std;
    #define N 150
    int head[N],to[N<<1],nxt[N<<1],cnt,n,f[N][2][2];
    inline void add(int u,int v) {
    	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    int vis[N][2];
    void dfs(int x,int y) {
    	int i;
    	f[x][1][0]=f[x][1][1]=1;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
    		dfs(to[i],x);
    	}
    	int mn[2],cc[2]; mn[0]=mn[1]=cc[0]=cc[1]=0;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
    		int t=to[i];
    		if(f[t][0][0]<f[t][1][0]) {
    			mn[0]+=f[t][0][0];
    			vis[t][0]=0;
    		}else {
    			mn[0]+=f[t][1][0];
    			cc[0]++;
    			vis[t][0]=1;
    		}
    		if(f[t][0][1]<f[t][1][1]) {
    			mn[1]+=f[t][0][1];
    			vis[t][1]=0;
    		}else {
    			mn[1]+=f[t][1][1];
    			cc[1]++;
    			vis[t][1]=1;
    		}
    	}
    	int d;
    	d=n+1;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
    		int t=to[i];
    		if(vis[t][1]==0) d=min(d,f[t][1][1]-f[t][0][1]);
    		else d=min(d,f[t][0][1]-f[t][1][1]);
    	}
    	if(cc[1]&1) {
    		f[x][0][1]=mn[1];
    		f[x][0][0]=mn[1]+d;
    	}else {
    		f[x][0][0]=mn[1];
    		f[x][0][1]=mn[1]+d;
    	}
    	d=n+1;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
    		int t=to[i];
    		if(vis[t][0]==0) d=min(d,f[t][1][0]-f[t][0][0]);
    		else d=min(f[t][0][0],f[t][1][0]);
    	}
    	if(cc[0]&1) {
    		f[x][1][0]+=mn[0];
    		f[x][1][1]+=mn[0]+d;
    	}else {
    		f[x][1][1]+=mn[0];
    		f[x][1][0]+=mn[0]+d;
    	}
    }
    int main() {
    	while(scanf("%d",&n)!=EOF&&n) {
    		memset(f,0,sizeof(f));
    		memset(head,0,sizeof(head)); cnt=0;
    		int i,x,y;
    		for(i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
    		dfs(1,0);
    		printf("%d
    ",min(f[1][0][1],f[1][1][1]));
    	}
    }
    
  • 相关阅读:
    linux常用命令三
    linux常用命令二
    redis持久化
    Linux环境redis集群搭建
    Maven常用命令
    Maven生成项目站点
    maven中import scope依赖方式解决单继承问题的理解
    maven使用assembly打包tar.gz文件
    Apache CXFjar包目录(转)
    WebService学习笔记一
  • 原文地址:https://www.cnblogs.com/suika/p/10205555.html
Copyright © 2011-2022 走看看