P3701 「伪模板」主席树
Posted hkttg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3701 「伪模板」主席树相关的知识,希望对你有一定的参考价值。
P3701 「伪模板」主席树
题目背景
byx和手气君都非常都非常喜欢种树。有一天,他们得到了两颗奇怪的树种,于是各自取了一颗回家种树,并约定几年后比一比谁种出来的树更加牛x。
题目描述
很快,这棵树就开花结果了。byx和手气君惊讶的发现,这是一棵主席树,树上长满了主席和主席的朋友们。这棵树上一共有五种人,主席(J),记者(HK),高人(W),女王(E)和膜法师(YYY)。他们发现,他们的主席树上的人数相同,都为N。
研究发现,这五种人的输赢如上图所示(一样的人不能PK),箭头指向输的人。至于为什么,留给同学们自己思考。
比赛如期进行。
byx和手气君要进行M场比赛,每一场比赛他们会选出树上的两个人来比较看谁更牛x。
第i个人寿命为Lifei秒,每次比完赛他们就会-1s。当他们生命为0s时他们就不能再比赛了。
同时,当J的寿命为0时,同一棵树上的YYY可以为他+1s。每个YYY只能给.每个J续一次。
那么问题来了
现在给定N,M(1≤N≤100,1≤M≤1000),A和B每一个人所属种类(J,HK,W,YYY或E)以及每一个人的生命,生命不超过50.请你算算A最多能够赢得多少场比赛呢。
数据保证每一场一定都有人用。两个人之间只能比一场。
输入输出格式
第一行包含两个数N,M,含义看上面。
第二行N个字串(J,HK,W,YYY或E),表示byx的人所属种类,用空格隔开。
第三行N个字串(J,HK,W,YYY或E),表示手气君的人所属种类,用空格隔开。
第四行N个数,表示byx的人的生命。
第五行N个数,表示手气君的人的生命。
输出格式:一个数,byx能赢的场次
输入输出样例
3 3 J W YYY J HK E 2 2 2 2 2 2
3
说明
第一场主席赢记者,第二场高人赢女王,第三场膜法师赢记者。
——————————————————————————————————————————————————————————————————
标题都是骗人的
本来还以为是主席树……看了题面发现是网络流……
觉得发现了一道极水的黑题
但是调了2个多小时……
为什么呢?
for (R int i = 1 + n; i <= 2 * n; ++ i) AddEdge(i, T, hp2[i]), AddEdge(T, i, 0);
for (R int i = 1; i <= n; ++ i) AddEdge(i + n, T, hp2[i]), AddEdge(T, i + n, 0);
这两句……有区别吗?
但是第一个就是输出0啊
R是register……去掉也不管用……
为啥?为啥?为啥?
这种玄学错误我还能调出来真的是谢天谢地了
求大佬解惑
ACcode
#include <algorithm> #include <cmath> #include <cstring> #include <cstdlib> #include <cstdio> #include <iostream> #include <map> #include <queue> #define R register typedef long long ll; typedef double db; const int INF = 1e9; const int MAXM = 10010; int n, m, hp1[110], hp2[110]; char name1[110][3], name2[110][3]; int ecnt = 1, head[MAXM], dep[MAXM]; struct Edge { int to, nxt, ret; }e[MAXM]; inline int read() { int num = 0, f = 1; char ch = getchar(); while (!isdigit(ch)) {if (ch == ‘-‘) f = -1; ch = getchar();} while (isdigit(ch)) {num = num * 10 + ch - ‘0‘; ch = getchar();} return num * f; } void AddEdge(int x, int y, int c) { e[++ ecnt].to = y; e[ecnt].ret = c; e[ecnt].nxt = head[x]; head[x] = ecnt; } int dfs(int x, int t, int maxFlow) { if (!maxFlow || x == t) return maxFlow; int ans = 0, v, f; for (int i = head[x]; i; i = e[i].nxt) { v = e[i].to; if (dep[v] == dep[x] + 1 && e[i].ret > 0) { f = dfs(v, t, std::min(maxFlow - ans, e[i].ret)); e[i].ret -= f; e[i ^ 1].ret += f; ans += f; } } if (ans < maxFlow) dep[x] = n + 1; return ans; } bool bfs(int s, int t) { std::queue<int> q; memset(dep, -1, sizeof(dep)); q.push(s); dep[s] = 0; int h, v; while (!q.empty()) { h = q.front(); q.pop(); for (int i = head[h]; i; i = e[i].nxt) { v = e[i].to; if (e[i].ret > 0 && dep[v] == -1) { q.push(v); dep[v] = dep[h] + 1; } } } return dep[t] != -1; } int Dinic(int s, int t) { int ans = 0; while (bfs(s, t)) ans += dfs(s, t, INF); return ans; } int main() { n = read(), m = read(); //std::cin >> n >> m; int add1 = 0, add2 = 0; for (R int i = 1; i <= n; ++ i) { scanf("%s", name1[i]); if (name1[i][0] == ‘Y‘) ++ add1; } for (R int i = 1; i <= n; ++ i) { scanf("%s", name2[i]); if (name2[i][0] == ‘Y‘) ++ add2; } for (R int i = 1; i <= n; ++ i) { hp1[i] = read(); //std::cin >> hp1[i]; if (name1[i][0] == ‘J‘) hp1[i] += add1; } for (R int i = 1; i <= n; ++ i) { hp2[i] = read(); //std::cin >> hp2[i]; if (name2[i][0] == ‘J‘) hp2[i] += add2; } int S = 0, T = 2 * n + 1; for (R int i = 1; i <= n; ++ i) AddEdge(S, i, hp1[i]), AddEdge(i, S, 0); /*for (R int i = 1 + n; i <= 2 * n; ++ i) AddEdge(i, T, hp2[i]), AddEdge(T, i, 0);*/ for (R int i = 1; i <= n; ++ i) AddEdge(i + n, T, hp2[i]), AddEdge(T, i + n, 0); for (R int i = 1; i <= n; ++ i) for (R int j = 1; j <= n; ++ j) { if (name1[i][0] == ‘J‘ && (name2[j][0] == ‘W‘ || name2[j][0] == ‘H‘)) AddEdge(i, j + n, 1), AddEdge(j + n, i, 0); if (name1[i][0] == ‘W‘ && (name2[j][0] == ‘Y‘ || name2[j][0] == ‘E‘)) AddEdge(i, j + n, 1), AddEdge(j + n, i, 0); if (name1[i][0] == ‘H‘ && (name2[j][0] == ‘W‘ || name2[j][0] == ‘E‘)) AddEdge(i, j + n, 1), AddEdge(j + n, i, 0); if (name1[i][0] == ‘E‘ && (name2[j][0] == ‘Y‘ || name2[j][0] == ‘J‘)) AddEdge(i, j + n, 1), AddEdge(j + n, i, 0); if (name1[i][0] == ‘Y‘ && (name2[j][0] == ‘H‘ || name2[j][0] == ‘J‘)) AddEdge(i, j + n, 1), AddEdge(j + n, i, 0); } std::cout << std::min(Dinic(S, T), m) << std::endl; return 0; }
QwQ无力吐槽
以上是关于P3701 「伪模板」主席树的主要内容,如果未能解决你的问题,请参考以下文章