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