CF-1218 or 1219 Bubble Cup 12--BubbleReactor

题意:https://codeforces.com/contest/1219/problem/A

每次占一个点,获取一个价值(与该点连通的未占数量),每次选的点必须与占的点相连。

问你最大获益

思路:

树dp出以某个树开始往环上走。

然后就开始考虑环我们怎么走,首先我想的是枚举以那颗树为起点,每次走一个相邻最小的(用优先队列)贪心,但是有100 1 1 1 1 1 50 50 50这种样例

所以就是整体考虑,简单区间dp(n方完成)

  1 class mymap
  2 {
  3 public:
  4     int tot,cnt_loop;
  5     int head[N],in[N],loop[N],SZ[N];
  6     int ele[N];
  7     int ans[N];//start
  8     bool is[N],vis[N];//vis是获取按顺序的循环用
  9     struct
 10     {
 11         int to,next,dis;
 12     }edge[N*2];
 13     void Init(int n)
 14     {
 15         tot=cnt_loop=0;
 16         for(int i=0;i<=n;++i)
 17             head[i]=in[i]=vis[i]=0,is[i]=1;
 18     }
 19     void add(int from,int to)
 20     {
 21         ++tot;
 22         edge[tot].to=to;
 23         //    edge[tot].dis=dis;
 24         edge[tot].next=head[from];
 25         head[from]=tot;
 26     }
 27     void get_loop(int n)
 28     {
 29         queue<int>q;
 30         for(int i=1;i<=n;++i)
 31             if(in[i]==1)
 32                 q.push(i);
 33         while(!q.empty())
 34         {
 35             int now=q.front();q.pop();
 36             is[now]=0;
 37             for(int i=head[now];i;i=edge[i].next)
 38             {
 39                 int to=edge[i].to;
 40                 in[to]--;
 41                 if(in[to]==1)
 42                     q.push(to);
 43             }
 44         }
 45         for(int i=1;i<=n;++i)
 46         {
 47             if(is[i])
 48             {
 49                 q.push(i);
 50                 while(!q.empty())
 51                 {
 52                     int now=q.front();q.pop();
 53                     loop[++cnt_loop]=now;
 54                     vis[now]=1;
 55                     bool have=0;
 56                     for(int j=head[now];j;j=edge[j].next)
 57                     {
 58                         int to=edge[j].to;
 59                         if(have)break;
 60                         if(is[to]&&!vis[to])
 61                         {
 62                             have=1;
 63                             q.push(to);
 64                         }
 65                     }
 66                 }
 67                 break;
 68             }
 69         }
 70     }
 71     void dfs1(int u,int fa)
 72     {
 73         SZ[u]=1;
 74         for(int i=head[u];i;i=edge[i].next)
 75         {
 76             int to=edge[i].to;
 77             if(to!=fa&&!is[to])
 78             {
 79                 dfs1(to,u);
 80                 SZ[u]+=SZ[to];
 81                 ele[u]+=ele[to];
 82             }
 83         }
 84         ele[u]+=SZ[u];
 85     }
 86     void dfs2(int u,int fa,int dep,int root,int id,int n)
 87     {
 88         ans[id]=max(ans[id],ele[u]+dep*(n-SZ[root]));
 89         for(int i=head[u];i;i=edge[i].next)
 90         {
 91             int to=edge[i].to;
 92             if(to!=fa&&!is[to])
 93             {
 94                 //    ele[to]=ele[u]-SZ[root]-SZ[to]+SZ[root]+SZ[root]-SZ[to];
 95                 ele[to]=ele[u]-SZ[to]+SZ[root]-SZ[to];
 96                 dfs2(to,u,dep+1,root,id,n);
 97             }
 98         }
 99     }
100 }TREE;
101 int realPos(int now,int len)
102 {
103     if(now>len)
104         now-=len;
105     else if(now<1)
106         now+=len;
107     return now;
108 }
109 
110 int dp1[N][2];
111 int dp2[N][2];
112 
113 int32_t main()
114 {
115 //    freopen("C:\\Users\\13606\\Desktop\\1.txt","r",stdin);
116     int n;
117     sc("%d",&n);
118     TREE.Init(n);
119     for(int i=1;i<=n;++i)
120     {
121         int u,v;
122         sc("%d%d",&u,&v);
123         u++;v++;
124         TREE.add(u,v);
125         TREE.add(v,u);
126         TREE.in[u]++;
127         TREE.in[v]++;
128     }
129     TREE.get_loop(n);
130     for(int i=1;i<=TREE.cnt_loop;++i)
131     {
132         TREE.dfs1(TREE.loop[i],-1);
133         TREE.dfs2(TREE.loop[i],-1,1,TREE.loop[i],i,n);
134     }
135 /*    int sum=0;
136     for(int i=1;i<=TREE.cnt_loop;++i)
137     {
138     //    pr("%d\n",TREE.ele[TREE.loop[i]]);
139         sum+=TREE.ele[TREE.loop[i]];
140     }*/
141     for(int i=1;i<=TREE.cnt_loop;++i)dp1[i][0]=TREE.ans[i],dp2[i][0]=TREE.SZ[TREE.loop[i]];
142     int LEN=TREE.cnt_loop;
143     int ANS=0;
144     for(int len=2;len<=LEN;++len)
145     {
146         for(int i=1;i<=LEN;++i)
147         {
148         //    int xx=realPos(i+1,LEN);
149         //    int yy=realPos(i+len-1,LEN);
150             dp1[i][1]=max(dp1[realPos(i+1,LEN)][0]+n-dp2[realPos(i+1,LEN)][0]+TREE.ele[TREE.loop[i]]-TREE.SZ[TREE.loop[i]]
151                     ,dp1[i][0]+n-dp2[i][0]+TREE.ele[TREE.loop[realPos(i+len-1,LEN)]]-TREE.SZ[TREE.loop[realPos(i+len-1,LEN)]]);
152             dp2[i][1]=dp2[realPos(i+1,LEN)][0]+TREE.SZ[TREE.loop[i]];
153         //    if(dp[xx][0].second+TREE.SZ[TREE.loop[i]]!=dp[i][0].second+TREE.SZ[TREE.loop[yy]])
154         //        pr("NONONO\n");
155             if(len==LEN)
156                 ANS=max(ANS,dp1[i][1]);
157         }
158         for(int i=1;i<=LEN;++i)
159             dp1[i][0]=dp1[i][1],dp2[i][0]=dp2[i][1];
160     }
161     pr("%d\n",ANS);
162     return 0;
163 }

 

上一篇:Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final)


下一篇:分段函数中的参数分离