【网络流24题】No. 20 深海机器人问题 (费用流)

【题意】

  深海资源考察探险队的潜艇将到达深海的海底进行科学考察。潜艇内有多个深海机器
人。 潜艇到达深海海底后, 深海机器人将离开潜艇向预定目标移动。 深海机器人在移动中还
必须沿途采集海底生物标本。 沿途生物标本由最先遇到它的深海机器人完成采集。 每条预定
路径上的生物标本的价值是已知的, 而且生物标本只能被采集一次。 本题限定深海机器人只
能从其出发位置沿着向北或向东的方向移动, 而且多个深海机器人可以在同一时间占据同一
位置。

输入文件示例
input.txt
1 1
2 2
1 2
3 4
5 6
7 2
8 10
9 3
2 0 0
2 2 2

输出文件示例
output.txt
42

 

 

 

【分析】

  求最大费用流,spfa时不要清-1,要清-INF!!!!!

  挑了我那么久,悲伤辣么大!!!

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 using namespace std;
  9 #define Maxn 1010
 10 #define INF 0xfffffff
 11 
 12 struct node
 13 {
 14     int x,y,f,o,c,next;
 15 }t[Maxn*Maxn];int len;
 16 int first[Maxn];
 17 
 18 int mymin(int x,int y) {return x<y?x:y;}
 19 int mymax(int x,int y) {return x>y?x:y;}
 20 
 21 void ins(int x,int y,int f,int c)
 22 {
 23     t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;
 24     t[len].next=first[x];first[x]=len;t[len].o=len+1;
 25     t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c;
 26     t[len].next=first[y];first[y]=len;t[len].o=len-1;
 27 }
 28 
 29 int st,ed;
 30 queue<int > q;
 31 int dis[Maxn],pre[Maxn],flow[Maxn];
 32 bool inq[Maxn];
 33 bool bfs()
 34 {
 35     while(!q.empty()) q.pop();
 36     // memset(dis,-1,sizeof(dis));
 37     for(int i=1;i<=ed;i++) dis[i]=-INF;
 38     memset(inq,0,sizeof(inq));
 39     q.push(st);dis[st]=0;flow[st]=INF;inq[st]=1;
 40     while(!q.empty())
 41     {
 42         int x=q.front();
 43         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 44         {
 45             int y=t[i].y;
 46             if(dis[y]<dis[x]+t[i].c)
 47             {
 48                 dis[y]=dis[x]+t[i].c;
 49                 pre[y]=i;
 50                 flow[y]=mymin(flow[x],t[i].f);
 51                 if(!inq[y])
 52                 {
 53                     inq[y]=1;
 54                     q.push(y);
 55                 }
 56             }
 57         }
 58         inq[x]=0;q.pop();
 59     }
 60     if(dis[ed]>-INF) return 1;
 61     return 0;
 62 }
 63 
 64 void output()
 65 {
 66     for(int i=1;i<=len;i++) if(t[i].f!=0&&(t[i].x==29||t[i].x==44||t[i].x==30))
 67      printf("%d->%d %d %d\n",t[i].x,t[i].y,t[i].f,t[i].c);
 68     printf("\n");
 69 }
 70 
 71 int max_flow()
 72 {
 73     int ans=0,sum=0;
 74     while(bfs())
 75     {
 76         sum+=dis[ed]*flow[ed];
 77         ans+=flow[ed];
 78         int now=ed;
 79         while(now!=st)
 80         {
 81             t[pre[now]].f-=flow[ed];
 82             t[t[pre[now]].o].f+=flow[ed];
 83             now=t[pre[now]].x;
 84         }
 85     }
 86     return sum;
 87 }
 88 
 89 int num[Maxn][Maxn],n,m,cnt;
 90 
 91 void init()
 92 {
 93     int a,b;
 94     scanf("%d%d",&a,&b);
 95     scanf("%d%d",&n,&m);
 96     len=0;cnt=0;
 97     memset(first,0,sizeof(first));
 98     for(int i=0;i<=n;i++)
 99      for(int j=0;j<=m;j++) num[i][j]=++cnt;
100     st=cnt+1;ed=st+1;
101     for(int i=0;i<=n;i++)
102      for(int j=0;j<m;j++)
103      {
104          int x;
105          scanf("%d",&x);
106          ins(num[i][j],num[i][j+1],1,x);
107          ins(num[i][j],num[i][j+1],INF,0);
108      }
109     for(int j=0;j<=m;j++)
110      for(int i=0;i<n;i++)
111      {
112          int x;
113          scanf("%d",&x);
114          ins(num[i][j],num[i+1][j],1,x);
115          ins(num[i][j],num[i+1][j],INF,0);
116      }
117     for(int i=1;i<=a;i++)
118     {
119         int k,x,y;
120         scanf("%d%d%d",&k,&x,&y);
121         ins(st,num[x][y],k,0);
122     }
123     for(int i=1;i<=b;i++)
124     {
125         int k,x,y;
126         scanf("%d%d%d",&k,&x,&y);
127         ins(num[x][y],ed,k,0);
128     }
129 }
130 
131 int main()
132 {
133     init();
134      
135     int ans;
136     ans=max_flow();
137     printf("%d\n",ans);
138     return 0;
139 }
View Code

 

 

2016-11-07 20:15:40

转载于:https://www.cnblogs.com/Konjakmoyu/p/6040447.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值