标签:
然后对a排序,二分删掉a中的一个元素,从大到小匹配判断是否合法,如果任何方案都不合法,则是不合法的直接退出
如果弄到最后都合法,这个答案就合法,不过要注意判断根的时候如果子树是偶数个不能额外加元素,也不能二分判断,而要直接判断合法性
例子:
19
15 13
4 17
图:
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 10005 7 #define inf 1061109567 8 using namespace std; 9 char ch; 10 int n,a,b,tot,ans,now[maxn],son[maxn<<1],pre[maxn<<1],deg[maxn],cnt,up[maxn],list[maxn]; 11 bool ok; 12 void read(int &x){ 13 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1; 14 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar()); 15 if (ok) x=-x; 16 } 17 void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b,deg[a]++;} 18 bool check(int x,int lim){ 19 for (int i=1,j=cnt;i<j;i++,j--){ 20 if (i==x) i++; if (j==x) j--; 21 if (list[i]+list[j]>lim) return false; 22 } 23 return true; 24 } 25 bool dfs(int u,int fa,int lim){ 26 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) 27 if (v!=fa) if (!dfs(v,u,lim)) return false; 28 cnt=0; 29 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) 30 if (v!=fa) list[++cnt]=up[v]+1; 31 if (!cnt) return true; 32 if (u!=1&&!(cnt&1)) list[++cnt]=0; 33 sort(list+1,list+cnt+1); 34 if (u==1&&!(cnt&1)) return check(0,lim); 35 int l=1,r=cnt,m; 36 while (l!=r){ 37 m=(l+r)>>1; 38 if (check(m,lim)) r=m; else l=m+1; 39 } 40 if (check(l,lim)) up[u]=list[l]; 41 else up[u]=inf; 42 return up[u]<=lim; 43 } 44 int calc(){ 45 int l=1,r=n-1,m; 46 while (l<r){ 47 m=(l+r)>>1; 48 if (dfs(1,0,m)) r=m; 49 else l=m+1; 50 } 51 return l; 52 } 53 int main(){ 54 while (~scanf("%d",&n)){ 55 tot=0; 56 memset(now,0,sizeof(now)); 57 memset(deg,0,sizeof(deg)); 58 memset(up,0,sizeof(up)); 59 for (int i=1;i<n;i++) read(a),read(b),put(a,b),put(b,a); 60 ans=1; 61 for (int i=1;i<=n;i++) ans+=(deg[i]-1)>>1; 62 printf("%d %d\n",ans,calc()); 63 } 64 return 0; 65 }
标签:
原文地址:http://www.cnblogs.com/chenyushuo/p/4918834.html