首先二分是比较明显的,二分答案val看Takahashi在游戏中是否能取到大于等于val的值,也就是Aoki要在Takahashi在到达每个点大于等于val的点前将那个点清空,我们使用DP来解决,dp[x]表示如果Takahashi从x出发,那么在游戏开始前,Aoki至少需要清空dp[x]个点才能让Takahashi达不到大于等于val的值,那么显然dp[x]=max(0,sum(dp[vi])-1),其中vi为x的子节点,如果dp[x]本身就大于等于val,则显然dp[x]需要再加一,最后如果dp[1]==0则Aoki胜利否则Takahashi胜利
这道题我没有想到怎么设dp状态,下面是具体代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstdlib> #include<queue> #define maxn 400009 using namespace std; int cnt,n,maxd,h[maxn],dp[maxn],a[maxn],b[maxn]; struct edge{ int to; int nex; }edge[maxn]; void adde() { int x,y; cin>>x>>y; edge[++cnt].to=y; edge[cnt].nex=h[x]; h[x]=cnt; edge[++cnt].to=x; edge[cnt].nex=h[y]; h[y]=cnt; } void dfs(int x,int fa,int val) { //cout<<x<<"!"<<fa<<" "<<dep<<endl; bool now=false; for (int i=h[x];i;i=edge[i].nex) { int to=edge[i].to; if (to==fa) continue; dfs(to,x,val); dp[x]+=dp[to]; now=true; } dp[x]=max(0,dp[x]-1); dp[x]+=a[x]>=val?1:0; // cout<<x<<"!"<<dp[x]<<endl; } bool check(int val) { for (int i=1;i<=n;i++) dp[i]=0; dfs(1,0,val); return dp[1]==0?false:true; } int main() { //dp[x] represents the less number of vertex to change before moving cin>>n; a[1]=0; for (int i=2;i<=n;i++) cin>>a[i],b[i]=a[i]; for (int i=1;i<n;i++) adde(); sort(b+1,b+1+n); int l=1,r=n,ans=0; while (l<=r) { int mid=(l+r)>>1; //cout<<l<<" "<<r<<" "<<b[mid]<<endl; if (check(b[mid])) l=mid+1,ans=mid; else r=mid-1; } cout<<b[ans]<<endl; return 0; }