题目:Economic Difficulties

传送门:https://codeforces.com/contest/1263/problem/F

题意:给了两棵tree:Ta(拥有a个节点,节点编号为[n+1, n+a]) Tb(拥有b个节点, 节点编号: [n+ a + 1, n + a + b]) 其中两颗tree的叶子节点按照dfs序依次连续连向 $ i, i \in [1, n] $节点,询问最多可以去掉多少的tree上节点,使得每一个$i , i \in [1, n]$ 仍然可以连通Ta,或者Tb的根节点。

分析:

1.做法一:https://codeforces.com/blog/entry/71844?locale=en

类似泛化背包,每个物品要么选择a,要么选择b,连续选择有额外贡献,假设cost_a[i,j]代表[i,j]区间选择a的贡献,cost_b[i,j]代表[i,j]区间选择b的贡献。

dp[i]代表前i个节点,方程:$$ dp[i] = max\{dp[j] + cost[j+1,i] \}$$

 #include <bits/stdc++.h>
using namespace std; vector< vector<int> > calc_cost(int vn, int n, vector<int> fa, vector<int> tg) {
vector< vector<int> > res(n+, vector<int>(n+));
for (int l = ; l <= n; l++) {
vector<int> deg(vn+);
for (int i = ; i <= vn ; i++) deg[fa[i]]++;
int val = ;
for (int r = l; r <= n; r++) {
for(int v = tg[r]; v != && deg[v] == ; --deg[v = fa[v]])
val++;
res[l][r] = val;
}
}
return res;
} int main() {
int n;
scanf("%d", &n);
vector< vector<int> > cost[];
for (int j = ; j < ; j++) {
int vn;
scanf("%d", &vn);
vector<int> fa(vn+);
vector<int> tg(n+);
for (int i = ; i <= vn; i++) scanf("%d", &fa[i]);
for (int i = ; i <= n; i++) scanf("%d", &tg[i]);
cost[j] = calc_cost(vn, n, fa, tg);
} vector<int> dp(n + , );
for (int i = ; i <= n; i++)
for (int j = ; j < i; j++)
dp[i] = max(dp[i], dp[j] + max(cost[][j+][i], cost[][j+][i]));
printf("%d", dp[n]);
return ;
}

2.基于最后的结果,我们肯定是选择Ta和Tb的一些节点,去除这些节点及其后代节点,考虑到这里,我们只要把每个节点控制的区间算出来,然后按照左端点或者有端点排序,然后做限制背包dp。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e4 + ;
const int INF = 1e9 + ;
vector< pair<pair<int,int>, int> > vec;
int sz[MAXN], st[MAXN], ed[MAXN], tg[MAXN];
vector<int> G[MAXN];
void dfs(int u) {
sz[u] = ;
st[u] = INF; ed[u] = -INF;
if(tg[u]) st[u] = ed[u] = tg[u];
for(auto v : G[u]) {
dfs(v);
sz[u] += sz[v];
st[u] = min(st[u], st[v]);
ed[u] = max(ed[u], ed[v]);
}
vec.push_back(make_pair(make_pair(ed[u], st[u] - ), sz[u]-(u == )));
}
int dp[MAXN];
int main() {
int n, a, x;
scanf("%d", &n);
for(int j = ; j < ; j++) {
scanf("%d", &a);
for(int i = ;i <= a; i++) {
scanf("%d", &x);
G[x].push_back(i);
}
for(int i = ; i <= n; i++) {
scanf("%d", &x);
tg[x] = i;
}
dfs();
for(int i = ; i <= a; i++) {
G[i].clear();
tg[i] = ;
}
}
sort(vec.begin(), vec.end());
for(auto it : vec) {
int l = it.first.second, r = it.first.first;
dp[r] = max(dp[r], dp[l] + it.second);
}
printf("%d", dp[n]);
return ;
}

3.和文理分科类似,该题也可以用网络流求解,然而我到现在都不知道为啥是对的。

#include <bits/stdc++.h>
using namespace std;
typedef int LL;
const int MAXN = 1e5 + ;
const int MAXM = 1e5 + ;
const int INF = 1e9 + ; namespace NWF {
struct Edge {
int to, nxt;LL f;
} e[MAXM << ];
int S, T, tot;
int ecnt, head[MAXN], cur[MAXN], dis[MAXN];
queue<int> q;
void init(int _S, int _T, int _tot){
ecnt = ; S = _S; T = _T; tot = _tot;
memset(head, , (tot + ) * sizeof(int));
}
void addEdge(int u, int v, LL f) {
e[++ecnt] = (Edge) {v, head[u], f}; head[u] = ecnt;
e[++ecnt] = (Edge) {u, head[v], }; head[v] = ecnt;
}
bool bfs() {
memset(dis, , (tot + ) * sizeof(int));
q.push(S); dis[S] = ;
while (!q.empty()) {
int u = q.front(), v; q.pop();
for (int i = cur[u] = head[u]; i ; i = e[i].nxt) {
if (e[i].f && !dis[v = e[i].to]) {
q.push(v);
dis[v] = dis[u] + ;
}
}
}
return dis[T];
}
LL dfs(int u, LL maxf) {
if (u == T) return maxf;
LL sumf = maxf;
for (int &i = cur[u]; i; i = e[i].nxt) {
if (e[i].f && dis[e[i].to] > dis[u]) {
LL tmpf = dfs(e[i].to, min(sumf, e[i].f));
e[i].f -= tmpf; e[i ^ ].f += tmpf;
sumf -= tmpf;
if (!sumf) return maxf;
}
}
return maxf - sumf;
}
LL dinic() {
LL ret = ;
while (bfs()) ret += dfs(S, INF);
return ret;
}
}
int faa[MAXN], fab[MAXN], tga[MAXN], tgb[MAXN];
int main() {
int n, A, B;
scanf("%d", &n);
scanf("%d", &A);
for(int i = ;i <= A; i++) scanf("%d", faa+i);
for(int i = ; i <= n; i++) scanf("%d", tga + i);
scanf("%d", &B);
for(int i = ;i <= B; i++) scanf("%d", fab+i);
for(int i = ; i <= n; i++) scanf("%d", tgb + i); NWF::init(A+B+,A+B+, A+B+);
for (int i = ; i <= A; i++) {
NWF::addEdge(NWF::S, i, );
NWF::addEdge(faa[i], i, INF);
}
for (int i = ; i <= B; i++) {
NWF::addEdge(A + i, A + fab[i], INF);
NWF::addEdge(A + i, NWF::T, );
}
for (int i = ; i <= n; i++)
NWF::addEdge(tga[i], A + tgb[i], INF); int ans = A - + B - - NWF::dinic();
printf("%d", ans);
return ;
}
#include <bits/stdc++.h>
using namespace std;
typedef int LL;
const int MAXN = 1e5 + ;
const int MAXM = 1e5 + ;
const int INF = 1e9 + ; namespace NWF {
struct Edge{
int to, nxt;LL f;
}e[MAXM << ];
int S, T, tot;
int ecnt, head[MAXN], cur[MAXN], pre[MAXN], num[MAXN], dis[MAXN];
queue<int> q;
void init(int _S, int _T, int _tot){
ecnt = ; S = _S; T = _T; tot = _tot;
memset(num, , (tot + ) * sizeof(int));
memset(head, , (tot + ) * sizeof(int));
}
inline void addEdge(int u, int v, LL f) {
e[++ecnt] = (Edge) {v, head[u], f}; head[u] = ecnt;
e[++ecnt] = (Edge) {u, head[v], }; head[v] = ecnt;
}
void bfs() {
memset(dis, , (tot + ) * sizeof(int));
q.push(T);
dis[T] = ;
while(!q.empty()) {
int u = q.front(), v; q.pop();
num[dis[u]]++;
for(int i = cur[u] = head[u]; i; i = e[i].nxt) {
if(!dis[v = e[i].to]) {
dis[v] = dis[u] + ;
q.push(v);
}
}
}
}
LL augment() {
LL flow = INF;
for(int i = S; i != T; i = e[cur[i]].to)
flow = min(flow, e[cur[i]].f);
for(int i = S; i != T; i = e[cur[i]].to) {
e[cur[i]].f -= flow;
e[cur[i] ^ ].f += flow;
}
return flow;
}
LL isap() {
bfs();
int u = S, v;
LL flow = ;
while(dis[S] <= tot) {
if(u == T) {
flow += augment();
u = S;
}
bool fg = ;
for(int i = cur[u]; i; i = e[i].nxt) {
if(e[i].f && dis[u] > dis[v = e[i].to]) {
pre[v] = u;
cur[u] = i;
u = v;
fg = ;
break;
}
}
if(fg) continue;
if(!--num[dis[u]]) break;
int maxDis = tot;
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].f && maxDis > dis[v = e[i].to]) {
maxDis = dis[v];
cur[u] = i;
}
}
num[dis[u] = maxDis + ]++;
if(u != S) u = pre[u];
}
return flow;
}
}
int faa[MAXN], fab[MAXN], tga[MAXN], tgb[MAXN];
int main() {
int n, A, B;
scanf("%d", &n);
scanf("%d", &A);
for(int i = ;i <= A; i++) scanf("%d", faa+i);
for(int i = ; i <= n; i++) scanf("%d", tga + i);
scanf("%d", &B);
for(int i = ;i <= B; i++) scanf("%d", fab+i);
for(int i = ; i <= n; i++) scanf("%d", tgb + i); NWF::init(A+B+,A+B+, A+B+);
for (int i = ; i <= A; i++) {
NWF::addEdge(NWF::S, i, );
NWF::addEdge(faa[i], i, INF);
}
for (int i = ; i <= B; i++) {
NWF::addEdge(A + i, A + fab[i], INF);
NWF::addEdge(A + i, NWF::T, );
}
for (int i = ; i <= n; i++)
NWF::addEdge(tga[i], A + tgb[i], INF); int ans = A - + B - - NWF::isap();
printf("%d", ans);
return ;
}

[CF Round603 Div2 F]Economic Difficulties的更多相关文章

  1. cf 442 div2 F. Ann and Books(莫队算法)

    cf 442 div2 F. Ann and Books(莫队算法) 题意: \(给出n和k,和a_i,sum_i表示前i个数的和,有q个查询[l,r]\) 每次查询区间\([l,r]内有多少对(i, ...

  2. Codeforces Round #603 (Div. 2) F. Economic Difficulties dp

    F. Economic Difficulties An electrical grid in Berland palaces consists of 2 grids: main and reserve ...

  3. Codeforces Round #603 (Div. 2)F. Economic Difficulties

    F. Economic Difficulties 题目链接: https://codeforces.com/contest/1263/problem/F 题目大意: 两棵树,都有n个叶子节点,一棵树正 ...

  4. Codeforces Round #603 F Economic Difficulties

    题目大意 给你两棵树,结点分别是1-A与1-B,然后给了N台设备,并且A树和B树的叶子结点(两棵树的叶子节点数量相同)都是链接电机的.问,最多可以删掉几条边使得每个设备都能连到任意一棵(或两棵)树的根 ...

  5. codeforces div2_603 F. Economic Difficulties(树dfs预处理+dp)

    题目连接:http://codeforces.com/contest/1263/problem/F 题意:有n个设备,上和下分别连接着一颗树,上下两棵树每棵树的叶子节点连接一个设备,两棵树的根节点都是 ...

  6. CF R638 div2 F Phoenix and Memory 贪心 线段树 构造 Hall定理

    LINK:Phoenix and Memory 这场比赛标题好评 都是以凤凰这个单词开头的 有凤来仪吧. 其实和Hall定理关系不大. 不过这个定理有的时候会由于 先简述一下. 对于一张二分图 左边集 ...

  7. CF#603 Div2

    差不多半年没打cf,还是一样的菜:不过也没什么,当时是激情,现在已是兴趣了,开心就好. A Sweet Problem 思维,公式推一下过了 B PIN Codes 队友字符串取余过了,结果今天早上一 ...

  8. Codeforces #451 Div2 F

    #451 Div2 F 题意 给出一个由数字组成的字符串,要求添加一个加号和等号,满足数字无前导 0 且等式成立. 分析 对于这种只有数字的字符串,可以快速计算某一区间的字符串变成数字后并取模的值,首 ...

  9. Codeforces #452 Div2 F

    #452 Div2 F 题意 给出一个字符串, m 次操作,每次删除区间 \([l,r]\) 之间的字符 \(c\) ,输出最后得到的字符串. 分析 通过树状数组和二分,我们可以把给定的区间对应到在起 ...

随机推荐

  1. Windows netcat 的工具的简单使用

    1. 下载 https://eternallybored.org/misc/netcat/ 2. 将目录添加到环境变量 C:\Work\netcat 3. 简单实验 4. 查看说明 UPDATE // ...

  2. [Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增)

    [Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增) 题面 n个点的图,点i和[l[i],i)的所有点连双向边.每次询问(l,r,x)表示x到[l,r]的所有点的最短 ...

  3. 03: django进阶篇

    1.1 cookie 1.cookie简介 1. cookie实质就是客户端硬盘中存放的键值对,利用这个特性可以用来做用户验证 2. 比如:{“username”: “dachengzi”} #再次访 ...

  4. XADC

    XADC实验 1.XADC概述 Xilinx7系列内部自带一个双通道12位分辨率的高速(1MSPS 1M sample per second)采样速率的模拟混合信号处理模块,双通道的ADC支持单极和差 ...

  5. STL 之 queue

    默认容器为双端队列deque 常用的函数有: empty Test whether container is empty (public member function ) size Return s ...

  6. tomcat 启动报错 解决办法 A child container failed during&nbsp

    转自:http://blog.sina.com.cn/s/blog_4e1e357d0102v55c.html 控制台报错: Caused by: org.apache.catalina.Lifecy ...

  7. Python 通过dmidecode获取Linux服务器硬件信息

    通过 dmidecode 命令可以获取到 Linux 系统的包括 BIOS. CPU.内存等系统的硬件信息,这里使用 python 代码来通过调用 dmidecode 命令来获取 Linux 必要的系 ...

  8. DRF框架 之基础配置

    Vue框架的总结 """ 1.vue如果控制html 在html中设置挂载点.导入vue.js环境.创建Vue对象与挂载点绑定 2.vue是渐进式js框架 3.vue指令 ...

  9. 2018-8-10-dotnet-core-编程规范

    title author date CreateTime categories dotnet core 编程规范 lindexi 2018-08-10 19:16:52 +0800 2018-05-0 ...

  10. ntsysv - 用于配置运行级别的简单接口

    总览 SYNOPSIS ntsysv [--back] [--level <levels>] 描述 DESCRIPTION ntsysv 是个用于配置运行级别服务(也可通过 chkconf ...