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 }

原文地址:https://www.cnblogs.com/--HPY-7m/p/12641560.html

时间: 2024-10-09 23:40:27

CF-1218 or 1219 Bubble Cup 12--BubbleReactor的相关文章

【题解】CF#Bubble Cup X - Finals E-Casinos and travel

天啊我怎么这么蠢……写了一个树形dp,的确发现记录的很多值并没有什么用,然而当时脑子没转过弯来还是写了这个树形dp……虽然能A但就不解释了,总之是个垃圾算法(??д??) #include <bits/stdc++.h> using namespace std; #define maxn 1000000 #define mod 1000000007 #define int long long int n, ans, rec, fa[maxn]; int g[maxn][2], f[maxn][

Bubble Cup 8 finals C. Party (575C)

题意: 给定n个人,分两天晚上去夜总会开派对,要求每天恰好有n/2个人去,且每人去的夜总会各不相同. 每个人对不同的晚上不同的夜总会有不同的满意度,求一个方案使得所有人的满意度之和最大. 夜总会数量=人的数量=n,2<=n<=20,且n是偶数. 0<=每一项满意度<=10^6. 时间限制2s,空间限制4MB. 题解: 在这题上卡了很久… 初看这题觉得是费用流…写完发现图建错了… 然后改成暴力枚举哪些人在第一天晚上去再跑费用流… 每个人只和对应晚上的夜总会连边,然后两天晚上的夜总会再

Bubble Cup 8 finals I. Robots protection

题意: 有一个正方形区域, 要求支持两个操作: 1.放置三角形,给定放置方向(有4个方向,直角边与坐标轴平行),直角顶点坐标,边长 2.查询一个点被覆盖了多少次 1<=正方形区域边长n<=5000 1<=询问数<=10^5 保证输入合法,三角形被正方形区域完全包含. 题解: 嗯这是一道数据结构题… 一开始我想起来之前做过但没做出来的一道三角形修改三角形查询的分块题… 然后…GEOTCBRL说,是k-d tree呀,CF上面有标程代码长度限制的… 然而我并不会用k-d tree做这个

Bubble Cup 8 finals G. Run for beer (575G)

题意: 给定一个带权无向图,每条边的代价为边权/当前速度,每次到达一个新节点,速度都会除以10. 求0号点到n-1号点的最小代价,如果多解输出点数最少的解,输出代价.路径点数.路径经过的点. 1<=边数<=10^5, 1<=点数<=10^5, 0<=边权<=9 题解: 比较有趣的一道题…难度不算太高,但一些地方比较容易想错… 这题的边代价可变本身并不是什么大问题,因为是图中所有边一起变大, 但是一开始就会遇到一个问题,就是总代价数字过大,没有办法直接存储和比较. 观察到

Bubble Cup 8 finals B. Bribes (575B)

题意: 给定一棵n个点和有向边构成的树,其中一些边是合法边,一些边是非法边, 经过非法边需要1的费用,并且经过之后费用翻倍. 给定一个长为m的序列,问从点1开始按顺序移动到序列中对应点的总费用. 1<=n<=10^5, 1<=m<=10^6 题解: 还是比较水的… 正解是各种方法求LCA,在点上打标记,最后DFS一遍就可以得到答案. 用tarjan求LCA可以做到总复杂度O(n*α)… 我傻傻地见树就剖,强行O(n log n log n)碾过去了… 每次把起点终点之间的路径的经过

Bubble Cup 8 finals H. Bots (575H)

题意: 简单来说就是生成一棵树,要求根到每个叶子节点上的路径颜色排列不同, 且每条根到叶子的路径恰有n条蓝边和n条红边. 求生成的树的节点个数. 1<=n<=10^6 题解: 简单计数. 显然,前n层的边的颜色是任意的,所以第i层就是2^i个点. 对于后n层,可以直接由上一层转移. 因为已经知道上一层合法的个数,那么如果现在每个点扩展两条边, 那么上一层的状态中,某种颜色的个数已经达到n的情况就有一条边不可扩展, 所以要减去2*C(i-1,n). 1 2 3 4 5 6 7 8 9 10 11

Bubble Cup X - Finals [Online Mirror]

来自FallDream的博客,未经允许,请勿转载,谢谢. 组了个菜鸡队打cf上的ACM比赛 比较快做完了8题但是菜的抠脚罚时巨多,所以最后被顶到了19名(居然没出首页) 自己的号自从上次疯狂掉分就没动过了,感觉像是红名橙名大佬中的一股清流. A.奇怪的贪心,我写了一发结果挂了,题解见大爷博客 B.dp方程很容易列出来,然后写个矩阵乘法就行了. C.每个点的位置决定了两边的白色小三角形的面积,这个面积是关于位置的一次函数,所以排序之后贪心就行了. D.二分+网络流判定 E.dp方程容易列出,然后换

Bubble Cup 8 finals E. Spectator Riots (575E)

题意: 一个长宽是100000单位的球场上有很多暴动的观众,每个观众都有一个速度v, 在一秒内,观众会等概率地移动到与原位置的曼哈顿距离<=v的地方(不会移动到界外). 你需要选取三个位置,这三个位置要求满足在一秒之后可能会出现观众. (这里不需要考虑概率大小,只要概率不为0就是满足的) 然后过这三点作圆,请选取在初始状态一秒后圆内观众数的期望值最大的方案输出. 如果有多种,输出半径最大的方案. 题解: 第一眼看起来非常可怕… 什么每秒移动速度呀…什么期望呀…先被吓死就做不了了… 其实是假装要扯

2018.9.22 Bubble Cup 11-Finals(Online Mirror,Div.2)

感受了一下ACM的感觉,然后被神题和神犇们暴踩了 夭寿啦,机房大佬非法组队啊 比赛前i207M插的"怕不是不到九点就要弃疗"的flag成功生效 一开始先扫了一遍题,我一开始以为A题是个扫一遍的题,然后发现自己naive了,遭到了wyt的嘲讽,不过i207M觉得这是个权值数据结构,然而我太蒻了并不会,于是他就去写了.然后就听到Zhang_RQ说B题是个圆方树,果断弃了,终于发现C很可做,这不是泡泡堂么,然后我写了一发过掉了.然后i207M交了一发$A$挂了,发现他读错题了,然后就听到zh