洛谷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 }
深深地明白自己的弱小