zoukankan      html  css  js  c++  java
  • agc034E

    题目描述

    题解

    最水的E题没有之一

    枚举最终点,显然可以转化成若干个数,每次把两个数各-1,不能减到负数

    那么如果最大数大于剩下的就无解,否则一定有解,具体每次把最大和次大拿出来-1,如果次次大>=2那么仍合法,如果为1且减的两个都为1,那么根据每次-2的原则即总和为偶数还存在另一个1,所以也合法

    发现放到树上之后还可能在子树内先消掉一部分,不可能同一个子树内的相互靠近因为不优,所以一定是子树内的朝着子树的根走

    设f[i]表示子树i内最小能剩下多少距离和,转移把和最大的子树拉出来判f即可求得当前的f,注意子树内部走最多只能走到子树的根而不是当前的根

    时间O(n^2)

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    #define inf 2147483647
    #define ll long long
    //#define file
    using namespace std;
    
    int a[4001][2],ls[2001],f[2001],sum[2001],sz[2001],len,n,i,j,k,l,ans;
    char b[2001];
    
    void New(int x,int y) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;}
    void dfs(int Fa,int t)
    {
    	int i,mx=0,Mx,Sum=0,s;
    	sz[t]=b[t]=='1',sum[t]=0;
    	
    	for (i=ls[t]; i; i=a[i][1])
    	if (a[i][0]!=Fa)
    	{
    		dfs(t,a[i][0]);
    		s=sum[a[i][0]]+sz[a[i][0]];
    		sz[t]+=sz[a[i][0]];
    		sum[t]+=s;
    		
    		Sum+=s;
    		if (s>mx) mx=s,Mx=a[i][0];
    	}
    	
    	if (mx && f[Mx]+sz[Mx]>Sum-mx)
    	f[t]=f[Mx]+sz[Mx]-(Sum-mx);
    	else
    	f[t]=sum[t]&1;
    }
    void work(int t)
    {
    	int i,j,k,l;
    	dfs(0,t);
    	if (!f[t]) ans=min(ans,sum[t]/2);
    }
    
    int main()
    {
    	#ifdef file
    	freopen("agc034E.in","r",stdin);
    	#endif
    	
    	scanf("%d",&n);
    	scanf("%s",b+1);
    	fo(i,1,n-1) scanf("%d%d",&j,&k),New(j,k),New(k,j);
    	
    	ans=inf;
    	fo(i,1,n) work(i);
    	printf("%d
    ",(ans==inf)?-1:ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    软考自查:面向对象设计
    软考自查:UML建模
    软考自查:数据库设计
    软考自查:数据流图(DFD)
    软考自查:多媒体基础知识
    .user.ini后门/上传黑名单绕过
    域渗透:钓鱼欺骗配合SMB重放攻击
    实现:ipc管道连接到远程计划任务种马
    实现:ipc命名管道连接
    实现:注册表的增删改查
  • 原文地址:https://www.cnblogs.com/gmh77/p/13861223.html
Copyright © 2011-2022 走看看