【网络流24题20】深海机器人问题

题面戳我
这里推荐一下相关的题目(我可以说是双倍经验题吗)
Luogu2045 方格取数加强版其实还是有点区别的啦

sol

这个题是说边上面有边权所以就不需要拆点了嗷。
每条边可以采集一次,那么肯定要连一条费用为收益容量为1的边。
那这条边就不可以走了吗?
显然不是。
所有还要连一条费用为0容量为\(inf\)的边。
所以就这样建边然后跑费用流就好啦。

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf = 1e9;
const int N = 2000;
struct edge{int to,next,w,cost;}a[N<<5];
int A,B,p,q,s,t,pos[100][100],tot,head[N],cnt=1,dis[N],vis[N],pe[N],ans;
queue<int>Q;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
void link(int u,int v,int w,int cost)
{
    a[++cnt]=(edge){v,head[u],w,cost};
    head[u]=cnt;
    a[++cnt]=(edge){u,head[v],0,-cost};
    head[v]=cnt;
}
bool spfa()
{
    memset(dis,63,sizeof(dis));
    dis[s]=0;Q.push(s);
    while (!Q.empty())
    {
        int u=Q.front();Q.pop();
        for (int e=head[u];e;e=a[e].next)
        {
            int v=a[e].to;
            if (a[e].w&&dis[v]>dis[u]+a[e].cost)
            {
                dis[v]=dis[u]+a[e].cost;pe[v]=e;
                if (!vis[v]) vis[v]=1,Q.push(v);
            }
        }
        vis[u]=0;
    }
    if (dis[t]==dis[0]) return false;
    int sum=inf;
    for (int i=t;i^s;i=a[pe[i]^1].to)
        sum=min(sum,a[pe[i]].w);
    ans-=sum*dis[t];
    for (int i=t;i^s;i=a[pe[i]^1].to)
        a[pe[i]].w-=sum,a[pe[i]^1].w+=sum;
    return true;
}
int main()
{
    A=gi();B=gi();p=gi();q=gi();
    for (int i=0;i<=p;i++)
        for (int j=0;j<=q;j++)
            pos[i][j]=++tot;
    s=tot+1;t=s+1;
    for (int i=0;i<=p;i++)
        for (int j=0;j<q;j++)
        {
            int val=gi();
            link(pos[i][j],pos[i][j+1],1,-val);
            link(pos[i][j],pos[i][j+1],inf,0);
        }
    for (int j=0;j<=q;j++)
        for (int i=0;i<p;i++)
        {
            int val=gi();
            link(pos[i][j],pos[i+1][j],1,-val);
            link(pos[i][j],pos[i+1][j],inf,0);
        }
    while (A--)
    {
        int k=gi(),x=gi(),y=gi();
        link(s,pos[x][y],k,0);
    }
    while (B--)
    {
        int r=gi(),x=gi(),y=gi();
        link(pos[x][y],t,r,0);
    }
    while (spfa());
    printf("%d\n",ans);
    return 0;
}
posted @ 2018-01-04 17:05  租酥雨  阅读(246)  评论(0编辑  收藏  举报