洛谷P4012 深海机器人问题(费用流)

传送门

 

图给的好坑……还得倒过来……

用大佬的图做个示范

我们考虑左图吧

把每一个点向下连边,容量$1$,费用为给出的价值(表示一个机器人可以过去取得标本)

再连一条边,容量$inf$,费用$0$(表示剩下的机器人过去无法取得标本)

然后向右连的边也一样

注意连边的顺序

然后源点向所有出发点连边,容量为机器人数,费用$0$,所有目的地向汇点连边,容量为机器人数,费用为$0$

跑个最大费用流

 1 //minamoto
 2 #include<bits/stdc++.h>
 3 #define inf 0x3f3f3f3f
 4 #define get(i,j) (i-1)*m+j
 5 using namespace std;
 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 7 char buf[1<<21],*p1=buf,*p2=buf;
 8 inline int read(){
 9     #define num ch-'0'
10     char ch;bool flag=0;int res;
11     while(!isdigit(ch=getc()))
12     (ch=='-')&&(flag=true);
13     for(res=num;isdigit(ch=getc());res=res*10+num);
14     (flag)&&(res=-res);
15     #undef num
16     return res;
17 }
18 const int N=1005,M=100005;
19 int ver[M],edge[M],head[N],Next[M],flow[M],tot=1;
20 int dis[N],disf[N],vis[N],Pre[N],last[N],n,m,s,t,a,b;
21 queue<int> q;
22 inline void add(int u,int v,int f,int e){
23     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,flow[tot]=f,edge[tot]=e;
24     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,flow[tot]=0,edge[tot]=-e;
25 }
26 bool spfa(){
27     memset(dis,0xef,sizeof(dis));
28     q.push(s),dis[s]=0,disf[s]=inf,Pre[t]=-1;
29     while(!q.empty()){
30         int u=q.front();q.pop();vis[u]=0;
31         for(int i=head[u];i;i=Next[i]){
32             int v=ver[i];
33             if(flow[i]&&dis[v]<dis[u]+edge[i]){
34                 dis[v]=dis[u]+edge[i],Pre[v]=u,last[v]=i;
35                 disf[v]=min(disf[u],flow[i]);
36                 if(!vis[v]) vis[v]=1,q.push(v);
37             }
38         }
39     }
40     return ~Pre[t];
41 }
42 int dinic(){
43     int maxcost=0;
44     while(spfa()){
45         int u=t;maxcost+=disf[t]*dis[t];
46         while(u!=s){
47             flow[last[u]]-=disf[t];
48             flow[last[u]^1]+=disf[t];
49             u=Pre[u];
50         }
51     }
52     return maxcost;
53 }
54 int main(){
55     a=read(),b=read(),n=read()+1,m=read()+1;
56     s=0,t=n*m+1;
57     for(int i=1;i<=n;++i)
58     for(int j=1;j<m;++j){
59         int x=read(),hh=get(i,j),tt=hh+1;
60         add(hh,tt,1,x);
61         add(hh,tt,inf,0);
62     }
63     for(int j=1;j<=m;++j)
64     for(int i=1;i<n;++i){
65         int x=read(),hh=get(i,j),tt=hh+m;
66         add(hh,tt,1,x);
67         add(hh,tt,inf,0);
68     }
69     for(int i=1;i<=a;++i){
70         int k=read(),x=read()+1,y=read()+1;
71         add(s,get(x,y),k,0);
72     }
73     for(int i=1;i<=b;++i){
74         int k=read(),x=read()+1,y=read()+1;
75         add(get(x,y),t,k,0);
76     }
77     printf("%d\n",dinic());
78     return 0;
79 }

 

posted @ 2018-08-20 10:56  bztMinamoto  阅读(191)  评论(0编辑  收藏  举报
Live2D