博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
E - Politics CodeForces - 1061E(最小费用流+观察分析)
阅读量:5310 次
发布时间:2019-06-14

本文共 8167 字,大约阅读时间需要 27 分钟。

 Politics
time limit per test 4 seconds
memory limit per test 256 megabytes
 

Problem Description

There are nn cities in the country.

Two candidates are fighting for the post of the President. The elections are set in the future, and both candidates have already planned how they are going to connect the cities with roads. Both plans will connect all cities using n−1n−1 roads only. That is, each plan can be viewed as a tree. Both of the candidates had also specified their choice of the capital among nn cities (xx for the first candidate and yy for the second candidate), which may or may not be same.

Each city has a potential of building a port (one city can have at most one port). Building a port in ii-th city brings aiai amount of money. However, each candidate has his specific demands. The demands are of the form:

  • kk xx, which means that the candidate wants to build exactly xx ports in the subtree of the kk-th city of his tree (the tree is rooted at the capital of his choice).

Find out the maximum revenue that can be gained while fulfilling all demands of both candidates, or print -1 if it is not possible to do.

It is additionally guaranteed, that each candidate has specified the port demands for the capital of his choice.

Input

The first line contains integers nn, xx and yy (1≤n≤5001≤n≤500, 1≤x,y≤n1≤x,y≤n) — the number of cities, the capital of the first candidate and the capital of the second candidate respectively.

Next line contains integers a1,a2,…,ana1,a2,…,an (1≤ai≤1000001≤ai≤100000) — the revenue gained if the port is constructed in the corresponding city.

Each of the next n−1n−1 lines contains integers uiui and vivi (1≤ui,vi≤n1≤ui,vi≤n, ui≠viui≠vi), denoting edges between cities in the tree of the first candidate.

Each of the next n−1n−1 lines contains integers u′iui′ and v′ivi′ (1≤u′i,v′i≤n1≤ui′,vi′≤n, u′i≠v′iui′≠vi′), denoting edges between cities in the tree of the second candidate.

Next line contains an integer q1q1 (1≤q1≤n1≤q1≤n), denoting the number of demands of the first candidate.

Each of the next q1q1 lines contains two integers kk and xx (1≤k≤n1≤k≤n, 1≤x≤n1≤x≤n) — the city number and the number of ports in its subtree.

Next line contains an integer q2q2 (1≤q2≤n1≤q2≤n), denoting the number of demands of the second candidate.

Each of the next q2q2 lines contain two integers kk and xx (1≤k≤n1≤k≤n, 1≤x≤n1≤x≤n) — the city number and the number of ports in its subtree.

It is guaranteed, that given edges correspond to valid trees, each candidate has given demand about each city at most once and that each candidate has specified the port demands for the capital of his choice. That is, the city xx is always given in demands of the first candidate and city yy is always given in the demands of the second candidate.

Output

Print exactly one integer — the maximum possible revenue that can be gained, while satisfying demands of both candidates, or -1 if it is not possible to satisfy all of the demands.

Examples
Input
Copy
4 1 2 1 2 3 4 1 2 1 3 3 4 1 2 2 3 1 4 2 1 3 4 1 1 2 3
Output
Copy
9
Input
Copy
5 1 1 3 99 99 100 2 1 2 1 3 3 4 3 5 1 3 1 2 2 4 2 5 2 1 2 3 1 2 1 2 2 1
Output
Copy
198
Input
Copy
4 1 2 1 2 3 4 1 2 1 3 3 4 2 1 2 4 4 3 1 1 4 2 4 1 2 4
Output
Copy
-1
Note

In the first example, it is optimal to build ports in cities 22, 33 and 44, which fulfills all demands of both candidates and gives revenue equal to 2+3+4=92+3+4=9.

In the second example, it is optimal to build ports in cities 22 and 33, which fulfills all demands of both candidates and gives revenue equal to 99+99=19899+99=198.

In the third example, it is not possible to build ports in such way, that all demands of both candidates are specified, hence the answer is -1.

 

Solution:

首先题意是 能否有一种方案,满足两个子图的要求,要求是结点与其后继(及后继的后继,即该点的所有孩子)的关系。

具体就是指 chi[i]=x,意思是i节点的后代必须有x个被标记。

考虑 这个i如果i选择好了x个(随意的选)是满足了chi[i]的需求,可是后代呢?假设ii是i的后代,chi[ii]=y,意思是ii这个的后代仅需要标记y个,如果i标记后代的时候顺便把ii的y标记了,那情况就变得很复杂了,为了避免这种情况呢,我们选择将他们分隔开,假设可以成功分隔的话,根据容斥原理,chi[i]需要标记x个,chi[ii]需要标记y个,那现在 chi[i]仅需要标记x-y个了,i的后代越多,减得越多,当然<0就不ok咯,假设rem=chi[i]-Σchi[k](k是i得后代) ,当rem<0,not ok,否则就有可能找到某种方式实现,只要把rem都标记出来就行了。(具体怎么找rem呢,就是用dfs把i后代与i之间的都可以找出来统计)。

因为选的方式有很多种,但仅能选一个,这就很像个二分图了,我们就可以把需求转化成求最大流即可。

具体建图就是呢:

S连结i(左子图的1,n) 容量就是rem[i],费用0(流代表需求)

j+n连结T(右子图的1,n) 容量就是rem[j],费用0(同上)

选择了左i,右i代表呢满足了i这个父母节点的需求 左par[i],右par[i] 连接,代价是-val[i],容量1(流过去代表满足了该i的一个需求,具体还要rem呢,都满足完才行,意思是最后最大流必须等于所有的左图chi[root]的需求),话说观察真的要挺自习才行,好啦,就这样?

1 #include 
2 #include
3 #include
4 #include
5 using namespace std; 6 const int N = 510; 7 const int M = 1010*1010; 8 const int inf_ = 0x3f; 9 typedef long long ll;10 11 struct Flow12 {13 struct node { int from, to, next; int val; int flow; }e[M<<1];14 int head[N << 1],S,T, cnt, vis[N << 1], from[N << 1]; queue
q; ll dis[N << 1],mxflow, micost;15 void init(int ss, int tt) { S = ss, T = tt, memset(head, -1, sizeof(head)); mxflow = micost = 0; }16 void add(int x, int y, int v, int f) { e[cnt] = node{ x, y, head[x], v, f }; head[x] = cnt++; }17 void addedge(int x, int y, int v, int f) { add(x, y, v, f); add(y, x, -v, 0);}18 int spfa()19 {20 memset(vis, 0, sizeof(vis)); memset(dis, inf_, sizeof(dis)); 21 dis[S] = 0; q.push(S); vis[S] = 1, from[S]=from[T] = -1;22 while (!q.empty())23 {24 int x = q.front(); q.pop(); vis[x] = 0;25 for (int i = head[x]; i != -1; i = e[i].next)26 {27 int to1 = e[i].to;28 if (e[i].flow>0 && dis[to1]>dis[x] + e[i].val)29 {30 dis[to1] = dis[x] + e[i].val; from[to1] = i;31 if (!vis[to1]) q.push(to1), vis[to1] = 1;32 }33 }34 }return from[T] != -1;35 }36 void mcmf()37 {38 int i = from[T],x;39 memset(&x, inf_, sizeof(x));40 while (i != -1) x = min(x, e[i].flow),i = from[e[i].from];41 i = from[T]; mxflow += x;42 while (i != -1) {micost += e[i].val*x; e[i].flow -= x; e[i ^ 1].flow += x; i = from[e[i].from];}43 }44 void work() { while (spfa())mcmf(); }45 void get_ans()46 {47 printf("%lld\n",-micost);48 }49 }G;50 51 struct tree52 {53 struct node { int to, next; }e[N<<1];54 int head[N], cnt, fa[N], par[N], q[N];55 void init() { memset(head, -1, sizeof(head)); }56 void add(int x, int y) { e[cnt] = node{ y,head[x] }; head[x] = cnt++; }57 void dfs(int x, int from, int lst)58 {59 if (from && q[x]) q[lst] -= q[x], par[x] = lst = x;60 else par[x] = lst;61 for (int i = head[x]; i != -1; i = e[i].next)62 {63 int to1 = e[i].to;64 if (to1 != from) dfs(to1, x, lst);65 }66 }67 bool check(int n) { for (int i = 1; i <= n; ++i) if (q[i] < 0) return 0; return 1; }68 }t[2];69 70 int a[1010];71 72 int main()73 {74 int n, ro1,ro2;75 G.init(0, 1001); t[0].init(), t[1].init();76 scanf("%d%d%d", &n,&ro1,&ro2);77 for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);78 for (int i = 1, x, y; i < n; ++i) scanf("%d%d", &x, &y), t[0].add(x, y), t[0].add(y, x);79 for (int i = 1, x, y; i < n; ++i) scanf("%d%d", &x, &y), t[1].add(x, y), t[1].add(y, x);80 int q, sum = 0;81 scanf("%d", &q);82 for (int i = 1, x, k; i <= q; ++i) scanf("%d%d", &x, &k), t[0].q[x] = k;83 scanf("%d", &q);84 for (int i = 1, x, k; i <= q; ++i) scanf("%d%d", &x, &k), t[1].q[x] = k;85 if (t[0].q[ro1] != t[1].q[ro2]) return puts("-1"), 0;86 sum = t[0].q[ro1];87 t[0].dfs(ro1, 0, ro1); t[1].dfs(ro2, 0, ro2);88 if (!t[0].check(n) || !t[1].check(n)) return puts("-1"), 0;89 for (int i = 1; i <= n; ++i) {90 G.addedge(t[0].par[i], t[1].par[i] + n, -a[i], 1);91 G.addedge(G.S, i, 0, t[0].q[i]);92 G.addedge(i + n, G.T, 0, t[1].q[i]);93 }94 G.work();95 if (G.mxflow != sum) return puts("-1"), 0;96 G.get_ans();97 return 0;98 }

 

转载于:https://www.cnblogs.com/SayGB/p/10398378.html

你可能感兴趣的文章
JQuery获取元素的方法总结
查看>>
Android学习路线总结,绝对干货
查看>>
CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...
查看>>
JS中如何判断null、undefined与NaN
查看>>
JavaScript中的数据类型
查看>>
静态代理模式
查看>>
HoloLens开发手记-全息Hologram
查看>>
HDU 4965 - Fast Matrix Calculation ( 矩阵快速幂 )
查看>>
继续边玩边学边颓废——2.13
查看>>
[置顶] 每个程序员都应该读的书
查看>>
转 Java内存管理思维导图
查看>>
Java List 转 String
查看>>
MVC 登录验证设置form验证
查看>>
Autolayout下使用代码改变frame无效
查看>>
iOS try catch
查看>>
32位linux(ubuntu) exec: arm-none-linux-gnueabi-g++未找到;The tslib functionality test failed!
查看>>
二叉树递归和非递归排序
查看>>
在iOS中base64解码与编码
查看>>
C重定向
查看>>
Hack语言类型化简介
查看>>