HDU 5383 Yu-Gi-Oh!(费用流)

来源:互联网 发布:apache性能监控 编辑:程序博客网 时间:2024/05/21 22:40

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5383


题意:游戏王同调召唤的方法,每只怪兽有等级和攻击力,两种不同类型的怪兽可以在一定限制下召唤出某一怪兽,具体限制要求可以参照题面


思路:先在那些限制要求下预处理出两种类型怪兽组合所能召唤出的那些怪兽,可以建二分图,对于两只怪兽攻击力计算有两种选择,可以相加计算攻击力,也可以组合新怪兽计算攻击力,所以可以按以下方式建图:


1.所有边容量均为1,源点向左部点连边费用为0,向右部点连边费用为该点攻击力,然后左部点向汇点连边费用为该点攻击力,向右部点连边费用为组合怪兽攻击力,右部点再向汇点连边费用为0,这样基于流量的限制,就可以使攻击力的两种计算方法体现出来了


2.所有边容量还是1,只有当组合的怪兽攻击力大于两怪兽累加和时才建边,费用为攻击力之差,源点到左部点连边费用为0,右部点向汇点连边连边费用为0,最后加上基础攻击力即可


注意因为求的是最大费用所以费用需为负,而且在跑费用流时,当费用变大时就停止答案的更新或者结束费用流



#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int MAXN = 1000;const int MAXM = 500000;const int INF = 0x3f3f3f3f;typedef long long ll;int res;struct Edge{    int from, to, next, cap, flow, cost;} edge[MAXM];int head[MAXN], tol;int pre[MAXN], dis[MAXN];bool vis[MAXN];int N;//节点总个数,节点编号从0~N-1void init(int n){    N = n;    tol = 0;    memset(head, -1, sizeof(head));}void addedge(int u, int v, int cap, int cost){    edge[tol].from = u;    edge[tol].to = v;    edge[tol].cap = cap;    edge[tol].cost = cost;    edge[tol].flow = 0;    edge[tol].next = head[u];    head[u] = tol++;    edge[tol].from = v;    edge[tol].to = u;    edge[tol].cap = 0;    edge[tol].cost = -cost;    edge[tol].flow = 0;    edge[tol].next = head[v];    head[v] = tol++;}bool spfa(int s, int t){    queue<int>q;    for (int i = 0; i < N; i++)    {        dis[i] = INF;        vis[i] = false;        pre[i] = -1;    }    dis[s] = 0;    vis[s] = true;    q.push(s);    while (!q.empty())    {        int u = q.front();        q.pop();        vis[u] = false;        for (int i = head[u]; i != -1; i = edge[i].next)        {            int v = edge[i].to;            if (edge[i].cap > edge[i].flow &&                    dis[v] > dis[u] + edge[i].cost )            {                dis[v] = dis[u] + edge[i].cost;                pre[v] = i;                if (!vis[v])                {                    vis[v] = true;                    q.push(v);                }            }        }    }    if (pre[t] == -1) return false;    else return true;}//返回的是最大流,cost存的是最小费用int minCostMaxflow(int s, int t, int &cost){    int flow = 0;    cost = 0;    while (spfa(s, t))    {        int Min = INF;        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])        {            if (Min > edge[i].cap - edge[i].flow)                Min = edge[i].cap - edge[i].flow;        }        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])        {            edge[i].flow += Min;            edge[i ^ 1].flow -= Min;            cost += edge[i].cost * Min;            //printf("**********%d %d\n", Min, cost);        }        res = min(cost, res);        flow += Min;    }    return flow;}struct monster{    int lev, atk;    monster(int lev = 0, int atk = 0) : lev(lev), atk(atk) {}};vector <monster> g[2];int gra[MAXN][MAXN], type[MAXN], id[MAXN];int main(){    int tt;    scanf("%d", &tt);    while (tt--)    {        memset(gra, 0, sizeof(gra));        g[0].clear(), g[1].clear();        int n, m;        scanf("%d%d", &n, &m);        int cl = 0, cr = 0;        for (int i = 1; i <= n; i++)        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            if (a == 0)                id[i] = cl++;            else                id[i] = cr++;            type[i] = a;            g[a].push_back(monster(b, c));        }        for (int i = 1; i <= m; i++)        {            int lev, atk, sum;            scanf("%d%d%d", &lev, &atk, &sum);            if (sum == 0)            {                for (int j = 0; j < cl; j++)                    for (int k = 0; k < cr; k++)                        if (g[0][j].lev + g[1][k].lev == lev)                            gra[j][k] = max(gra[j][k], atk);            }            else if (sum == 1)            {                int x;                scanf("%d", &x);                if (type[x] == 0)                {                    for (int k = 0; k < cr; k++)                        if (g[0][id[x]].lev + g[1][k].lev == lev)                            gra[id[x]][k] = max(gra[id[x]][k], atk);                }                else                {                    for (int j = 0; j < cl; j++)                        if (g[0][j].lev + g[1][id[x]].lev == lev)                            gra[j][id[x]] = max(gra[j][id[x]], atk);                }            }            else            {                int x, y;                scanf("%d%d", &x, &y);                if (type[x] == 1) swap(x, y);                if (g[0][id[x]].lev + g[1][id[y]].lev == lev)                {                    gra[id[x]][id[y]] = max(gra[id[x]][id[y]], atk);                }            }        }        // for (int i = 0; i < cl; i++)        // {        //     for (int j = 0; j < cr; j++)        //         printf("%d ", gra[i][j]);        //     printf("\n");        // }        int s = cl + cr, t = s + 1;        init(t + 1);        for (int i = 0; i < cl; i++)            for (int j = 0; j < cr; j++)                if (gra[i][j] > 0)                    addedge(i, j + cl, 1, -gra[i][j]);        for (int i = 0; i < cl; i++)        {            addedge(s, i, 1, 0);            addedge(i, t, 1, -g[0][i].atk);        }        for (int i = 0; i < cr; i++)        {            addedge(s, i + cl, 1, -g[1][i].atk);            addedge(i + cl, t, 1, 0);        }//        for(int i = 0; i < tol; i++)//            printf("%d %d %d %d\n", edge[i].from, edge[i].to, edge[i].cap, edge[i].cost);        int ans;        res = INF;        minCostMaxflow(s, t, ans);        printf("%d\n", -res);    }    return 0;}




#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int MAXN = 1000;const int MAXM = 1001000;const int INF = 0x3f3f3f3f;typedef long long ll;int res;struct Edge{    int from, to, next, cap, flow, cost;} edge[MAXM];int head[MAXN], tol;int pre[MAXN], dis[MAXN];bool vis[MAXN];int N;//节点总个数,节点编号从0~N-1void init(int n){    N = n;    tol = 0;    memset(head, -1, sizeof(head));}void addedge(int u, int v, int cap, int cost){    edge[tol].from = u;    edge[tol].to = v;    edge[tol].cap = cap;    edge[tol].cost = cost;    edge[tol].flow = 0;    edge[tol].next = head[u];    head[u] = tol++;    edge[tol].from = v;    edge[tol].to = u;    edge[tol].cap = 0;    edge[tol].cost = -cost;    edge[tol].flow = 0;    edge[tol].next = head[v];    head[v] = tol++;}bool spfa(int s, int t){    queue<int>q;    for (int i = 0; i < N; i++)    {        dis[i] = INF;        vis[i] = false;        pre[i] = -1;    }    dis[s] = 0;    vis[s] = true;    q.push(s);    while (!q.empty())    {        int u = q.front();        q.pop();        vis[u] = false;        for (int i = head[u]; i != -1; i = edge[i].next)        {            int v = edge[i].to;            if (edge[i].cap > edge[i].flow &&                    dis[v] > dis[u] + edge[i].cost )            {                dis[v] = dis[u] + edge[i].cost;                pre[v] = i;                if (!vis[v])                {                    vis[v] = true;                    q.push(v);                }            }        }    }    if (pre[t] == -1) return false;    else return true;}//返回的是最大流,cost存的是最小费用int minCostMaxflow(int s, int t, int &cost){    int flow = 0;    cost = 0;    while (spfa(s, t))    {        int Min = INF;        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])        {            if (Min > edge[i].cap - edge[i].flow)                Min = edge[i].cap - edge[i].flow;        }        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])        {            edge[i].flow += Min;            edge[i ^ 1].flow -= Min;            cost += edge[i].cost * Min;        }        res = min(cost, res);        flow += Min;    }    return flow;}struct monster{    int lev, atk;    monster(int lev = 0, int atk = 0) : lev(lev), atk(atk) {}};vector <monster> g[2];int gra[MAXN][MAXN], type[MAXN], id[MAXN];int main(){    int tt;    scanf("%d", &tt);    while (tt--)    {        memset(gra, 0, sizeof(gra));        g[0].clear(), g[1].clear();        int n, m;        scanf("%d%d", &n, &m);        int cl = 0, cr = 0, sum = 0;        for (int i = 1; i <= n; i++)        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            if (a == 0)                id[i] = cl++;            else                id[i] = cr++;            sum += c;            type[i] = a;            g[a].push_back(monster(b, c));        }        for (int i = 1; i <= m; i++)        {            int lev, atk, sum;            scanf("%d%d%d", &lev, &atk, &sum);            if (sum == 0)            {                for (int j = 0; j < cl; j++)                    for (int k = 0; k < cr; k++)                        if (g[0][j].lev + g[1][k].lev == lev)                            gra[j][k] = max(gra[j][k], atk);            }            else if (sum == 1)            {                int x;                scanf("%d", &x);                if (type[x] == 0)                {                    for (int k = 0; k < cr; k++)                        if (g[0][id[x]].lev + g[1][k].lev == lev)                            gra[id[x]][k] = max(gra[id[x]][k], atk);                }                else                {                    for (int j = 0; j < cl; j++)                        if (g[0][j].lev + g[1][id[x]].lev == lev)                            gra[j][id[x]] = max(gra[j][id[x]], atk);                }            }            else            {                int x, y;                scanf("%d%d", &x, &y);                if (type[x] == 1) swap(x, y);                if (g[0][id[x]].lev + g[1][id[y]].lev == lev)                {                    gra[id[x]][id[y]] = max(gra[id[x]][id[y]], atk);                }            }        }        // for (int i = 0; i < cl; i++)        // {        //  for (int j = 0; j < cr; j++)        //      printf("%d ", gra[i][j]);        //  printf("\n");        // }        int s = cl + cr, t = s + 1;        init(t + 1);        for (int i = 0; i < cl; i++)            for (int j = 0; j < cr; j++)                if (gra[i][j] > 0 && gra[i][j] > g[0][i].atk + g[1][j].atk)                    addedge(i, j + cl, INF, g[0][i].atk + g[1][j].atk - gra[i][j]);        for (int i = 0; i < cl; i++)        {            addedge(s, i, 1, 0);            //  addedge(i, t, 1, -g[0][i].atk);        }        for (int i = 0; i < cr; i++)        {            //  addedge(s, i + cl, 1, -g[1][i].atk);            addedge(i + cl, t, 1, 0);        }        int ans;        res = 0;        minCostMaxflow(s, t, ans);        printf("%d\n", sum - res);    }    return 0;}


0 0
原创粉丝点击