[CodeForces-375E]Red and Black Tree

Posted skylee的OI博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CodeForces-375E]Red and Black Tree相关的知识,希望对你有一定的参考价值。

题目大意:
  给你一棵带边权的树,每个结点可能是红色或者黑色,你可以交换若干个点对使得任意一个红点到达与其最近的黑点的距离小于等于m。

思路:
  动态规划。
  f[i][j][k]表示以i为根的子树中,连向结点j,子树中已经确定有k个是黑点所需要的最小交换次数。
  best[i][k]表示以i为根的子树,已经确定有k个是黑点所需要的最小交换次数。
  设当前根为x,子结点为y,连向结点i,总共确定了k个黑点,新确定了l个黑点,转移方程为:
  f[x][i][k]=min(min{f[x][i][k-l]+best[y][l]},min{f[x][i][k-l+1]+f[y][i][l]-!col[i]});
  当然要判断新连向的点与当前根的距离,这可以事先跑一遍O(n^3)的Floyd。
  最后会被卡内存,据lyx介绍,由于n<=500,可以用uint16卡过去。

 1 #include<cstdio>
 2 #include<vector>
 3 typedef unsigned short uint16; 
 4 inline int getint() {
 5     register char ch;
 6     while(!__builtin_isdigit(ch=getchar()));
 7     register int x=ch^0;
 8     while(__builtin_isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^0);
 9     return x;
10 }
11 template<typename _T1,typename _T2>
12 inline _T1 min(const _T1 &a,const _T2 &b) {
13     return a<b?a:b;
14 }
15 template<typename _T1,typename _T2>
16 inline _T1 max(const _T1 &a,const _T2 &b) {
17     return a>b?a:b;
18 }
19 const uint16 inf=~0;
20 const uint16 N=501;
21 bool col[N];
22 uint16 n,s;
23 int m;
24 int dis[N][N];
25 std::vector<uint16> e[N];
26 inline void add_edge(const uint16 &u,const uint16 &v,const int &w) {
27     e[u].push_back(v);
28     e[v].push_back(u);
29     dis[u][v]=dis[v][u]=w;
30 }
31 uint16 f[N][N][N],best[N][N],size[N];
32 void dfs(const uint16 &x,const uint16 &par) {
33     for(uint16 i=0;i<e[x].size();i++) {
34         const uint16 &y=e[x][i];
35         if(y==par) continue;
36         dfs(y,x);
37     }
38     for(register uint16 i=1;i<=n;i++) {
39         if(dis[x][i]>m) continue;
40         size[x]=1;
41         f[x][i][1]=!col[i];
42         for(register uint16 j=0;j<e[x].size();j++) {
43             const uint16 &y=e[x][j];
44             if(y==par) continue;
45             for(register uint16 k=min(s,size[x]+size[y]);;k--) {
46                 uint16 tmp=inf;
47                 for(register uint16 j=max(k-size[x],0);j<=min(k,size[y]);j++) {
48                     tmp=min(tmp,f[x][i][k-j]+best[y][j]);
49                 }
50                 for(register uint16 j=max(k-size[x],0)+1;j<=min(k,size[y]);j++) {
51                     tmp=min(tmp,f[x][i][k-j+1]+f[y][i][j]-!col[i]);
52                 }
53                 f[x][i][k]=tmp;
54                 if(!k) break;
55             }
56             size[x]+=size[y];
57         }
58     }
59     for(register uint16 i=1;i<=s;i++) {
60         best[x][i]=inf;
61         for(register uint16 j=1;j<=n;j++) {
62             best[x][i]=min(best[x][i],f[x][j][i]);
63         }
64     }
65 }
66 int main() {
67     n=getint(),m=getint();
68     for(register uint16 i=1;i<=n;i++) {
69         s+=(col[i]=getint());
70     }
71     __builtin_memset(dis,0x3f,sizeof dis);
72     for(register uint16 i=1;i<n;i++) {
73         const uint16 u=getint(),v=getint();
74         const int w=getint();
75         add_edge(u,v,w);
76     }
77     for(register uint16 k=1;k<=n;k++) {
78         for(register uint16 i=1;i<=n;i++) {
79             for(register uint16 j=1;j<=n;j++) {
80                 dis[i][j]=i==j?0:min(dis[i][j],dis[i][k]+dis[k][j]);
81             }
82         }
83     }
84     __builtin_memset(f,0xff,sizeof f);
85     __builtin_memset(best,0xff,sizeof best);
86     dfs(1,0);
87     __builtin_printf("%d\n",best[1][s]==inf?-1:best[1][s]);
88     return 0;
89 }

 

以上是关于[CodeForces-375E]Red and Black Tree的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 375D D. Tree and Queries

[Codeforces375D]Tree and Queries(莫队算法)

CodeForces 375D Tree and Queries 莫队||DFS序

CodeForces 375D. Tree and Queries树上启发式合并

E - Red and Blue Graph(组合数学)

E - Red and Blue Graph(组合数学)