LuoguP4012 深海机器人问题(费用流)
题目描述
深海资源考察探险队的潜艇将到达深海的海底进行科学考察。
潜艇内有多个深海机器人。潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动。
深海机器人在移动中还必须沿途采集海底生物标本。沿途生物标本由最先遇到它的深海机器人完成采集。
每条预定路径上的生物标本的价值是已知的,而且生物标本只能被采集一次。
本题限定深海机器人只能从其出发位置沿着向北或向东的方向移动,而且多个深海机器人可以在同一时间占据同一位置。
用一个P×Q 网格表示深海机器人的可移动位置。西南角的坐标为 (0,0),东北角的坐标为 (Q,P) 。
给定每个深海机器人的出发位置和目标位置,以及每条网格边上生物标本的价值。
计算深海机器人的最优移动方案, 使深海机器人到达目的地后,采集到的生物标本的总价值最高。
输入输出格式
输入格式:
文件的第 1 行为深海机器人的出发位置数 a,和目的地数 b 。
第 2 行为 P 和 Q 的值。
接下来的 P+1 行,每行有 Q 个正整数,表示向东移动路径上生物标本的价值,行数据依从南到北方向排列。
再接下来的 Q+1 行,每行有 P 个正整数,表示向北移动路径上生物标本的价值,行数据依从西到东方向排列。
接下来的 a 行,每行有 3 个正整数 k,x,y,表示有 k 个深海机器人从 (x,y)位置坐标出发。
再接下来的 b 行,每行有 3 个正整数 r,x,y ,表示有 r 个深海机器人可选择 (x,y)位置坐标作为目的地。
a行和b行输入时横纵坐标要反过来
输出格式:
输出采集到的生物标本的最高总价值.
解题思路:
输入喷我一脸。
在边界建两条流,一条流量为1有费用,一条为0无费用
代码:
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 const int oo=0x3f3f3f3f; 6 struct pnt{ 7 int hd; 8 int pre; 9 int lst; 10 int dis; 11 int val; 12 bool vis; 13 }p[100000]; 14 struct ent{ 15 int twd; 16 int lst; 17 int vls; 18 int dis; 19 }e[1000000]; 20 int cnt; 21 int n,m; 22 int s,t; 23 int ns,nt; 24 int no[101][101]; 25 std::queue<int>Q; 26 void ade(int f,int t,int v,int d) 27 { 28 cnt++; 29 e[cnt].twd=t; 30 e[cnt].vls=v; 31 e[cnt].dis=d; 32 e[cnt].lst=p[f].hd; 33 p[f].hd=cnt; 34 return ; 35 } 36 bool Spfa(void) 37 { 38 for(int i=1;i<=t;i++) 39 { 40 p[i].dis=p[i].val=oo; 41 p[i].vis=false; 42 } 43 p[t].pre=-1; 44 p[s].dis=0; 45 p[s].vis=true; 46 while(!Q.empty()) 47 Q.pop(); 48 Q.push(s); 49 while(!Q.empty()) 50 { 51 int x=Q.front(); 52 Q.pop(); 53 p[x].vis=false; 54 for(int i=p[x].hd;i;i=e[i].lst) 55 { 56 int to=e[i].twd; 57 if(p[to].dis>p[x].dis+e[i].dis&&e[i].vls>0) 58 { 59 p[to].dis=p[x].dis+e[i].dis; 60 p[to].val=std::min(p[x].val,e[i].vls); 61 p[to].pre=x; 62 p[to].lst=i; 63 if(p[to].vis) 64 continue; 65 p[to].vis=true; 66 Q.push(to); 67 } 68 } 69 } 70 return p[t].pre!=-1; 71 } 72 int Ek(void) 73 { 74 int ans=0; 75 while(Spfa()) 76 { 77 ans+=p[t].dis*p[t].val; 78 for(int i=t;i!=s;i=p[i].pre) 79 { 80 e[p[i].lst].vls-=p[t].val; 81 e[((p[i].lst-1)^1)+1].vls+=p[t].val; 82 } 83 } 84 return ans; 85 } 86 int main() 87 { 88 // freopen("a.in","r",stdin); 89 scanf("%d%d",&ns,&nt); 90 scanf("%d%d",&n,&m); 91 for(int i=0;i<=n;i++) 92 for(int j=0;j<=m;j++) 93 no[i][j]=++cnt; 94 s=cnt+1; 95 t=cnt+2; 96 cnt=0; 97 for(int i=0;i<=n;i++) 98 { 99 for(int j=0;j<m;j++) 100 { 101 int x; 102 scanf("%d",&x); 103 ade(no[i][j],no[i][j+1],1,-x); 104 ade(no[i][j+1],no[i][j],0,x); 105 ade(no[i][j],no[i][j+1],oo,0); 106 ade(no[i][j+1],no[i][j],0,0); 107 } 108 } 109 for(int j=0;j<=m;j++) 110 { 111 for(int i=0;i<n;i++) 112 { 113 int x; 114 scanf("%d",&x); 115 ade(no[i][j],no[i+1][j],1,-x); 116 ade(no[i+1][j],no[i][j],0,x); 117 ade(no[i][j],no[i+1][j],oo,0); 118 ade(no[i+1][j],no[i][j],0,0); 119 } 120 } 121 for(int i=1;i<=ns;i++) 122 { 123 int a,b,c; 124 scanf("%d%d%d",&c,&a,&b); 125 ade(s,no[a][b],c,0); 126 ade(no[a][b],s,0,0); 127 } 128 for(int i=1;i<=nt;i++) 129 { 130 int a,b,c; 131 scanf("%d%d%d",&c,&a,&b); 132 ade(no[a][b],t,c,0); 133 ade(t,no[a][b],0,0); 134 } 135 printf("%d\n",-Ek()); 136 return 0; 137 }