Central Post Office (Shiraz University Local Contest 2011 ) 树状dp

uva C – Central Post Office

low[i][0] 表示不回到i点 ,以i节点为根,其子树的最小值,low[i][1] 表示回到i点

up[i][0] 表示不回到i点 ,除去以i节点为根,其子树的最小值,up[i][1] 表示回到i点

#include<iostream>
#include<cstring>
#include <cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include <set>
#include<ctime>
#include<cmath>
#include <cstdlib>
#include<algorithm>
using namespace std;

#define LL long long
const int N=10010;
const int INF=(( 1<<31)-1);

vector<int> G[N];
bool vis[N];
int low[N][2],up[N][2],dp[N][2];
void dfs1(int u,int f){
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i]; 
		if(v!=f){
			dfs1(v,u);
			low[u][1]+=low[v][1]+2;
		}
	}
	bool flag=0;
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i]; 
		if(v!=f){
			int x=low[u][1]-low[v][1]-2+1+low[v][0];
			if(!flag) low[u][0]=x;
			else low[u][0]=min(x,low[u][0]);
			flag=1;
		}
	}
}
int ok(int u,int x,int f,int sum){
	int ans=INF;
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(v!=f&&v!=x){
			ans=min(ans,sum-low[x][1]-2-low[v][1]-2+low[v][0]+1);
		}
	}
	ans=min(ans,sum-low[x][1]-2-up[u][1]+up[u][0]);
	return ans;
}
void dfs2(int u,int f){
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i]; 
		if(v!=f){
			up[v][1]+=up[u][1]+low[u][1]-low[v][1]-2+2;
		}
	}	
	int sum=up[u][1];
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(v!=f){
			sum+=low[v][1]+2;
		}
	}
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(v!=f){	
			up[v][0]=ok(u,v,f,sum)+1;
		}
	}
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i]; 
		if(v!=f){
			dfs2(v,u);
		}
	}	
}
int main(){
	int n,T;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			G[i].clear();
		}
		for(int i=1;i<=n;i++){
			int num;
			scanf("%d",&num);
			while(num--){
				int x;
				scanf("%d",&x);
				G[i].push_back(x);
			}
		}
		//cout<<endl;
		//for(int i=1;i<=n;i++){
		//    cout<<i<<" : ";
		//    for(int j=0;j<G[i].size();j++){
		//        cout<<G[i][j]<<" ";
		//    }
		//    cout<<endl;
		//}
		memset(low,0,sizeof(low));
		memset(up,0,sizeof(up));
		dfs1(1,0);
		dfs2(1,0);

		//cout<<endl;
		//for(int i=1;i<=n;i++)
		//	cout<<low[i][0]<<" "<<low[i][1]<<endl;
		//cout<<endl;

		//cout<<endl;
		//for(int i=1;i<=n;i++)
		//	cout<<up[i][0]<<" "<<up[i][1]<<endl;
		//cout<<endl;

		int  ans=INF;
		for(int i=1;i<=n;i++){
			int x=min(low[i][0]+up[i][1],low[i][1]+up[i][0]);
			ans=min(ans,x);
		}
		printf("%d\n",ans);
	}
}

  

posted @ 2012-05-13 17:05  HaoHua_Lee  阅读(214)  评论(0编辑  收藏  举报