您的位置:首页 > 理论基础 > 计算机网络

【网络流24题】深海机器人(最大费用流)

2017-08-28 18:32 357 查看

传送门

深海机器人

题意:给定带一次性边权网格与若干机器人的起终点,规定起终点必须被机器人经过的次数,求所有机器人能够得到的最大边权和.

I think

最大费用流,源点向起点连边,终点向汇点连边,方格上的点向相邻点连流量为1费用为val的边.除此之外,对于题目要求,”多个机器人可以在同一时间占据同一位置“,方格上的点还要向相邻点连流量为Inf,费用为0的边.

注意题面所给最后所给起点与终点的坐标横纵是相反的对于方格中的点的编号,可用mp[][]数组+P*Q循环进行预处理.

Code

#include<cstdio>
#include<queue>
using namespace std;

const int sm = 260;
const int sn = 3080;
const int Inf = 0x3f3f3f3f;

int P,Q,tot=1,S,T;
int to[sn],hd[sm],nxt[sn],c[sn],f[sn];
int pre[sm],vis[sm],cst[sm],mp[17][17];

int Min(int x,int y) { return x<y?x:y; }
void Add(int u,int v,int x,int y) {
to[++tot]=v,nxt[tot]=hd[u],hd[u]=tot,c[tot]=x,f[t
4000
ot]=y;
to[++tot]=u,nxt[tot]=hd[v],hd[v]=tot,c[tot]=0,f[tot]=-y;
}
int Point(int x,int y) { return (Q+1)*y+x+1; }
void SPFA() {
int Ans=0,df,t;
queue<int>q;
while(true) {
for(int i=0;i<=T;++i) cst[i]=-Inf;
q.push(S),cst[S]=0;
while(!q.empty()) {
t=q.front(),q.pop(),vis[t]=0;
for(int i=hd[t];i;i=nxt[i])
if(c[i]>0&&cst[to[i]]<cst[t]+f[i]) {
cst[to[i]]=cst[t]+f[i];
pre[to[i]]=i;
if(!vis[to[i]]) {
vis[to[i]]=1;
q.push(to[i]);
}
}
}
if(cst[T]==-Inf) break;
df=Inf;
for(int i=T;i!=S;i=to[pre[i]^1])
df=Min(df,c[pre[i]]);
for(int i=T;i!=S;i=to[pre[i]^1])
c[pre[i]]-=df,c[pre[i]^1]+=df;
Ans+=df*cst[T];
}
printf("%d\n",Ans);
}
int main() {
int a,b,u,v,k,cnt=0;
scanf("%d%d%d%d",&a,&b,&P,&Q);
S=(P+1)*(Q+1)+1,T=S+1;
for(int i=0;i<=P;++i)
for(int j=0;j<=Q;++j)
mp[j][i]=++cnt;
for(int i=0;i<=P;++i)
for(int j=0;j<Q;++j) {
scanf("%d",&u);
Add(mp[j][i],mp[j+1][i],1,u);
Add(mp[j][i],mp[j+1][i],Inf,0);
}
for(int i=0;i<=Q;++i)
for(int j=0;j<P;++j) {
scanf("%d",&u);
Add(mp[i][j],mp[i][j+1],1,u);
Add(mp[i][j],mp[i][j+1],Inf,0);
}
for(int i=1;i<=a;++i)
scanf("%d%d%d",&k,&u,&v),Add(S,mp[v][u],k,0);
for(int i=1;i<=b;++i)
scanf("%d%d%d",&k,&u,&v),Add(mp[v][u],T,k,0);
SPFA();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: