【Libre OJ #6224】「网络流 24 题」深海机器人问题 / 题解

原题地址

题目描述

深海资源考察探险队的潜艇将到达深海的海底进行科学考察。

潜艇内有多个深海机器人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。

深海机器人在移动中还必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。

每条预定路径上的生物标本的价值是已知的,而且生物标本只能被采集一次。

本题限定深海机器人只能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一位置。

用一个 $ ext{P} imes ext{Q}$网格表示深海机器人的可移动位置。西南角的坐标为 $(0,0)$ ,东北角的坐标为 $(Q,P)$ 。

给定每个深海机器人的出发位置和目标位置,以及每条网格边上生物标本的价值。

计算深海机器人的最优移动方案, 使深海机器人到达目的地后,采集到的生物标本的总价值最高。

输入和输出

输入

文件的第 1 行为深海机器人的出发位置数 $ ext a$,和目的地数 $ ext{b}$ 。

第 2 行为 $ ext{P}$ 和 $ ext{Q}$ 的值。

接下来的 $ ext{P} +1$ 行,每行有 $ ext{Q}$ 个正整数,表示向东移动路径上生物标本的价值,行数据依从南到北方向排列。

再接下来的 $ ext{Q} +1 $ 行,每行有 $ ext{P}$ 个正整数,表示向北移动路径上生物标本的价值,行数据依从西到东方向排列。

接下来的 $ ext{a}$ 行,每行有 3 个正整数 $ ext{k,x,y}$ ,表示有 $ ext{k}$ 个深海机器人从 $( ext{x,y})$ 位置坐标出发。

再接下来的 $ ext{b}$ 行,每行有 3 个正整数 $ ext{r,x,y}$ ,表示有 $ ext{r}$ 个深海机器人可选择 $( ext{x,y})$ 位置坐标作为目的地。

输出

输出采集到的生物标本的最高总价值。

样例

输入
1 1
2 2
1 2
3 4
5 6
7 2
8 10
9 3
2 0 0
2 2 2
输出
42

数据范围和提示

$1≤P,Q≤15$

$1leq aleq 4$

$1leq bleq 6$

思路

由标题可知,依然是网络流。

相邻的点要连两条边,一条流量为 1 费用为标本价值,另一条流量为无限,费用为 0 。解释:两种情况:第一个机器人拿到了标本;之后的机器人单纯地经过这个点。

建图的时候费用取相反数,然后跑最小费用最大流就可以求出最大价值了。

代码

#include 
#define maxn 8000
#define pu(i,j) ((i-1)*Q+j)
using namespace std;
struct Edge{
    int to,next,flow,cost;
    Edge(int a=0,int b=0,int c=0,int d=0){
        to=a,next=b,flow=c,cost=d;
    }
}l[maxn<<5];
struct Node{
    int pre,id;
    Node(int a=0,int b=0){
        pre=a,id=b;
    }
}cha[maxn];
int head[maxn],cnt=1,dis[maxn],vis[maxn],s,t;
int neflow[maxn],maxflow,mincost;
inline void Add(int a,int b,int c,int d){
    l[++cnt]=Edge(b,head[a],c,d);head[a]=cnt;
    l[++cnt]=Edge(a,head[b],0,-d);head[b]=cnt;
}
inline bool spfa(){
    queueq;
    fill(dis+1,dis+t+1,INT_MAX);
    q.push(s);dis[s]=0;
    neflow[s]=INT_MAX;
    while(!q.empty()){
        int hq=q.front();q.pop();vis[hq]=0;
        for (int i=head[hq];i;i=l[i].next){
            int v=l[i].to;
            if (dis[v]>dis[hq]+l[i].cost&&l[i].flow){
                dis[v]=dis[hq]+l[i].cost;
                neflow[v]=min(neflow[hq],l[i].flow);
                cha[v]=Node(hq,i);
                if (!vis[v]){
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    return dis[t]