出题人居然是个哲学家。。
26%的程序,太SB了。。。本来我的想法也是二分+贪心,但是贪心是个怪怪的SX贪心。。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #include<time.h> 7 #define inf 0x7fffffff 8 struct edge{ 9 int u,v,id; 10 }e[400005]; 11 int tot,go[400005],first[200005],next[400005]; 12 int Tot,Go[400005],First[200005],Next[400005]; 13 int c[200005],b[200005],son[200005],ans,vis[200005],pd; 14 int pass[400005],op[400005],C[400005],Cnt,block,sum,B[200005]; 15 int id1,id2; 16 int n,k; 17 int read(){ 18 char ch=getchar();int t=0,f=1; 19 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 20 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 21 return t*f; 22 } 23 void Dfs(int x,int fa){ 24 if (vis[x]) return; 25 c[x]=b[x];son[x]=1; 26 for (int i=first[x];i;i=next[i]){ 27 int pur=go[i]; 28 if (pur==fa) continue; 29 if (pass[i]) continue; 30 Dfs(pur,x); 31 son[x]+=son[pur]; 32 c[x]+=c[pur]; 33 } 34 if (c[x]&&(n-c[x]>0)) ans=std::min(ans,std::max(son[x],n-son[x])); 35 } 36 void sbpianfen(){ 37 ans=inf; 38 Dfs(1,0); 39 printf("%d ",ans); 40 } 41 void insert(int x,int y){ 42 tot++; 43 go[tot]=y; 44 next[tot]=first[x]; 45 first[x]=tot; 46 pass[tot]=1; 47 } 48 void add(int x,int y){ 49 insert(x,y);op[tot]=tot+1;insert(y,x);op[tot]=tot-1; 50 } 51 void Insert(int x,int y){ 52 Tot++; 53 Go[Tot]=y; 54 Next[Tot]=First[x]; 55 First[x]=Tot; 56 } 57 void Add(int x,int y){ 58 Insert(x,y);Insert(y,x); 59 } 60 int bfs(int x){ 61 int h=1,t=1; 62 bool ck=0; 63 c[1]=x;vis[x]=1;if (b[x]) ck=1; 64 while (h<=t){ 65 int now=c[h++]; 66 for (int i=First[now];i;i=Next[i]){ 67 int pur=Go[i]; 68 if (vis[pur]) continue; 69 c[++t]=pur; 70 vis[pur]=1; 71 if (b[pur]) ck=1; 72 } 73 } 74 if (!ck) pd=1; 75 return t; 76 } 77 void dFs(int x){ 78 if (x==n){ 79 pd=0; 80 int bl=0; 81 for (int i=1;i<=n;i++) 82 First[i]=0; 83 Tot=0; 84 for (int i=1;i<n;i++) 85 if (!e[i].id) Add(e[i].u,e[i].v); 86 for (int i=1;i<=n;i++) 87 vis[i]=0; 88 for (int i=1;i<=n;i++) 89 if (!vis[i]) 90 bl=std::max(bl,bfs(i)); 91 if (pd==0) ans=std::min(ans,bl); 92 return; 93 } 94 e[x].id=1; 95 dFs(x+1); 96 e[x].id=0; 97 dFs(x+1); 98 } 99 void sxpianfen(){ 100 for (int i=1;i<n;i++) e[i].id=0; 101 dFs(1); 102 } 103 void clear(int x){ 104 int h=1,t=1; 105 C[1]=x; 106 bool ppp=1; 107 if (b[x]) Cnt++,ppp=0; 108 vis[x]=1;b[x]=0; 109 while (h<=t){ 110 int now=C[h++]; 111 for (int i=first[now];i;i=next[i]){ 112 int pur=go[i]; 113 if (pass[i]) continue; 114 if (vis[pur]) continue; 115 C[++t]=pur; 116 vis[pur]=1; 117 if (b[pur]) Cnt++,ppp=0; 118 b[pur]=0; 119 } 120 } 121 if (ppp) { 122 pd=1; 123 return; 124 } 125 if (t>block) pd=1; 126 sum-=t; 127 } 128 void work(int x,int mid,int fa,int Edge){ 129 if (c[x]==1&&b[fa]==1&&son[x]<=block) { 130 pass[Edge]=1; 131 pass[op[Edge]]=1; 132 clear(x); 133 id1=x;id2=fa; 134 if (pd) return; 135 return; 136 } 137 else 138 if (k-Cnt-c[x]==1&&b[x]==1&&sum-son[x]<=block){ 139 pass[Edge]=1; 140 pass[op[Edge]]=1; 141 clear(fa); 142 id1=x;id2=fa; 143 if (pd) return; 144 return; 145 } 146 else 147 if (c[x]==1&&son[x]<=block&&son[fa]>=block){ 148 pass[Edge]=1; 149 pass[op[Edge]]=1; 150 clear(x); 151 id1=x;id2=fa; 152 if (pd) return; 153 return; 154 }else 155 if (k-Cnt-c[x]==1&&sum-son[x]==block){ 156 pass[Edge]=1; 157 pass[op[Edge]]=1; 158 clear(fa); 159 id1=x;id2=fa; 160 if (pd) return; 161 return; 162 } 163 for (int i=first[x];i;i=next[i]){ 164 int pur=go[i]; 165 if (pur==fa) continue; 166 if (vis[pur]) continue; 167 if (pass[i]) continue; 168 work(pur,mid,x,i); 169 } 170 } 171 bool check(int mid){ 172 for (int i=1;i<n;i++) std::swap(e[rand()%(n-1)+1],e[rand()%(n-1)+1]); 173 for (int i=1;i<=n;i++) first[i]=0; 174 tot=0; 175 for (int i=1;i<n;i++) 176 add(e[i].u,e[i].v); 177 block=mid;pd=0; 178 for (int i=1;i<=tot;i++) 179 pass[i]=0; 180 for (int i=1;i<=n;i++) 181 b[i]=B[i],vis[i]=0; 182 id1=1;id2=0;vis[0]=1; 183 sum=n;Cnt=0; 184 for (int i=1;i<=k;i++){ 185 if (vis[id1]&&vis[id2]) break; 186 if (k-Cnt==1) break; 187 if (!vis[id1]){ 188 Dfs(id1,0); 189 work(id1,mid,0,0); 190 }else{ 191 Dfs(id2,0); 192 work(id2,mid,0,0); 193 } 194 if (pd) return 0; 195 } 196 for (int i=1;i<=n;i++) 197 if (!vis[i]) clear(i); 198 if (pd) return 0; 199 return 1; 200 } 201 void solve(){ 202 int l=n/k,r=n,Ans=n; 203 while (l<=r){ 204 int mid=(l+r)/2; 205 if (check(mid)) r=mid-1,Ans=mid; 206 else l=mid+1; 207 } 208 printf("%d ",Ans); 209 } 210 void solve2(){ 211 int l=n/k,r=n,Ans=n; 212 while (l<=r){ 213 int mid=(l+r)/2; 214 if (check(mid)) r=mid-1,Ans=mid; 215 else l=mid+1; 216 } 217 int Tn=Ans; 218 l=n/k,r=n,Ans=n; 219 while (l<=r){ 220 int mid=(l+r)/2; 221 if (check(mid)) r=mid-1,Ans=mid; 222 else l=mid+1; 223 } 224 Tn=std::min(Tn,Ans); 225 printf("%d ",Tn); 226 } 227 int main(){ 228 //♂ 229 freopen("deep.in","r",stdin); 230 freopen("deep.out","w",stdout); 231 srand(time(NULL)); 232 ans=inf; 233 n=read();k=read(); 234 for (int i=1;i<n;i++){ 235 int x=read(),y=read(); 236 add(x,y); 237 e[i].u=x;e[i].v=y; 238 } 239 for (int i=1;i<=k;i++){ 240 int x=read(); 241 b[x]=1;B[x]=1; 242 } 243 if (n<=20) {sxpianfen();printf("%d ",ans);return 0;} 244 if (k==1) {printf("%d ",n);return 0;} 245 if (k==2) {sbpianfen();return 0;} 246 if (n<=2000) {solve();return 0;} 247 if (k==3) {solve2();return 0;} 248 if (k==n) {printf("%d ",1);return 0;} 249 if (k==n-1) {printf("%d ",2);return 0;} 250 solve(); 251 }
AC程序不知道短到哪里去了
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define N 200005 7 int tot,go[N*2],next[N*2],first[N]; 8 int n,k,b[N],fa[N],mx[N],sum[N],vis[N],c[N]; 9 int read(){ 10 char ch=getchar();int t=0,f=1; 11 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 12 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 13 return t*f; 14 } 15 void insert(int x,int y){ 16 tot++; 17 go[tot]=y; 18 next[tot]=first[x]; 19 first[x]=tot; 20 } 21 void add(int x,int y){ 22 insert(x,y);insert(y,x); 23 } 24 void bfs(){ 25 int h=1,t=1;for (int i=1;i<=n;i++) vis[i]=0; 26 c[1]=1; 27 vis[1]=1; 28 while (h<=t){ 29 int now=c[h++]; 30 for (int i=first[now];i;i=next[i]){ 31 int pur=go[i]; 32 if (vis[pur]) continue; 33 vis[pur]=1; 34 c[++t]=pur; 35 fa[pur]=now; 36 } 37 } 38 } 39 bool check(int mid){ 40 int f; 41 memset(sum,0,sizeof sum); 42 memset(mx,0,sizeof mx); 43 for (int i=n;i>=1;i--){ 44 int u=c[i]; 45 if (b[u]) mx[u]=mid-1; 46 else sum[u]++; 47 f=(mx[u]>=sum[u])?mx[u]-sum[u]:-sum[u]; 48 if (u==1&&f<0) return 0; 49 if (f<0) sum[fa[u]]-=f; 50 else mx[fa[u]]=std::max(mx[fa[u]],f); 51 } 52 return 1; 53 } 54 int main(){ 55 n=read();k=read(); 56 for (int i=1;i<n;i++){ 57 int x=read(),y=read(); 58 add(x,y); 59 } 60 for (int i=1;i<=k;i++){ 61 int x=read(); 62 b[x]=1; 63 } 64 bfs(); 65 int l=n/k,r=n,ans; 66 while (l<=r){ 67 int mid=(l+r)>>1; 68 if (check(mid)) r=mid-1,ans=mid; 69 else l=mid+1; 70 } 71 printf("%d ",ans); 72 }