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);
}
}

浙公网安备 33010602011771号