• 角色扮演


    题意:

    有n种技能,每个技能有两个属性,分别对应着物理伤害,魔法伤害,现在有m个连招,如果连续两个技能都选择同一种属性就会得到一个属性加成,否则就会丢失一些伤害,现在需要使得伤害最大化,求这个最大的伤害。

    题解:

    因为两个属性物理或者魔法只能选择一种属性,那么很容易就想到最小割,那么再用总伤害减去最小割就是最大的技能伤害,但是对于伤害加成和伤害丢失怎么办呢?有一种建图方式。

    注:S 到 p1的容量是AP(魔法)加成 + 伤害丢失 , p2 到 T的容量是AD(物理)加成 + 伤害丢失。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int M = 1e6 + 7;
    const int N = 1e6 + 7;
    const int INF = (1 << 31) - 1;
    struct edge
    {
    	int v, c, f, nxt;
    } e[M << 1];
    LL sum;
    int vis[N], S, T, ecnt, head[N], dep[N], cur[N], n, m;
    
    void adde (int u, int v, int c) 
    {
    	e[ecnt] = (edge) {v, c, 0, head[u]}, head[u] = ecnt++;
    	e[ecnt] = (edge) {u, 0, 0, head[v]}, head[v] = ecnt++;
    }
    
    int BFS (int S)
    {
    	queue <int> q;
    	q.push(S);
    	memset (vis, 0, sizeof vis);
    	vis[S] = 1, dep[S] = 0;
    	while (!q.empty())
    	{
    		int u = q.front();
    		q.pop();
    		for (int it = head[u]; it != -1; it = e[it].nxt)
    		{
    			int v = e[it].v;
    			if (!vis[v] && e[it].c > e[it].f) 
    			{
    				vis[v] = 1;
    				dep[v] = dep[u] + 1;
    				q.push(v);
    			}
    		}
    	}
    	return vis[T];
    }
    
    LL DFS (int u, LL flow)
    {
    	if (u == T || flow == 0) return flow;
    	LL tot = 0, F;
    	for (int it = cur[u]; it != -1; it = e[it].nxt)
    	{
    		cur[u] = it;
    		int v = e[it].v;
    		if (dep[u] + 1 == dep[v] && (F = DFS(v, min(flow, (LL) e[it].c - e[it].f))) > 0)
    		{
    			e[it].f += F;
    			e[it ^ 1].f -= F;
    			tot += F;
    			flow -= F;
    			if (flow == 0) break;
    		}
    	}
    	return tot;
    }
    
    LL dinic ()
    {
    	LL maxf = 0;
    	while (BFS(S))
    	{
    		for (int i = 0; i <= T; ++ i) cur[i] = head[i];
    		maxf += DFS(S, INF);
    	}
    	return maxf;
    }
    
    int main ()
    {
    	memset (head, -1, sizeof head);
    	scanf ("%d%d", &n, &m);
    	T = 2 * m + n + 1;
    	for (int i = 1; i <= n; ++ i)
    	{
    		int P, D;
    		scanf ("%d%d", &P, &D);
    		sum += P + D;
    		adde (S, i, P);
    		adde (i, T, D);
    	}
    	int tmp = n + 1;
    	for (int i = 1; i <= m; ++ i)
    	{
    		int u, v, P, D, z;
    		scanf ("%d%d%d%d%d", &u, &v, &D, &P, &z);
    		sum += P + D + z;
    		adde (S, tmp, P + z);
    		adde (tmp, u, INF);
    		adde (tmp, v, INF);
    		++tmp;
    		adde (u, tmp, INF);
    		adde (v, tmp, INF);
    		adde (tmp, T, D + z);
    		++tmp;
    	}
    	cout << sum - dinic() << endl;
    	return 0;
    }
    

      

  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/xgtao/p/6024090.html
Copyright © 2020-2023  润新知