1. 程式人生 > >P3701 「偽模板」主席樹

P3701 「偽模板」主席樹

map 比一比 head 網絡 就是 問題 num 區別 輸入輸出格式

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能贏的場次

輸入輸出樣例

輸入樣例#1:
3 3
J W YYY
J HK E
2 2 2
2 2 2
輸出樣例#1:
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 「偽模板」主席樹