题目描述
传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物。某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝物就藏在右下角,迷宫的进出口在左上角。当然,迷宫中的通路不是平坦的,到处都是陷阱。Dr.Kong决定让他的机器人卡多去探险。
但机器人卡多从左上角走到右下角时,只会向下走或者向右走。从右下角往回走到左上角时,只会向上走或者向左走,而且卡多不走回头路。(即:一个点最多经过一次)。当然卡多顺手也拿走沿路的每个宝物。
Dr.Kong希望他的机器人卡多尽量多地带出宝物。请你编写程序,帮助Dr.Kong计算一下,卡多最多能带出多少宝物。
输入
第一行: K 表示有多少组测试数据。
接下来对每组测试数据:
第1行: M N
第2~M+1行: Ai1 Ai2 ……AiN (i=1,…..,m)
2≤k≤5 1≤M, N≤50 0≤Aij≤100 (i=1,….,M; j=1,…,N)
所有数据都是整数。 数据之间有一个空格。
输出
对于每组测试数据,输出一行:机器人卡多携带出最多价值的宝物数
样例输入
2
2 3
0 10 10
10 10 80
3 3
0 3 9
2 8 5
5 7 100
样例输出
120
134
题意:左上走到右下捡数字,走两次,求最大和
求最大费用最大流只需把费用变成负数,用spfa找到一条费用最大的路
还有就是要拆点建图,一个点拆成两个,其中一条边费用为对应数字,流量1,另一条边费用为0,流量1
然后设个超级源点和超级汇点,分别连接左上,右下
这个和poj3422有些类似,那个题是走k次,这个只走两次
拆点建图,建完的图,就是每个点拆为两个,1&1',s→1→→1’→2→→2' 然后1↓3→→3'→4→→4’
大概就这个意思,上下左右也要连起来
代码注释:
#include<iostream> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define N 5050 #define inf 0x7fffffff int n,m,s,t,maxflow,o; struct node { int u,v,c,f,next; } a[100000]; int visit[N]; int pre[N]; int head[N]; int dis[N]; int map[55][55]; void add(int u,int v,int c,int f) //c为费用,f流量 { a[o].u=u,a[o].v=v,a[o].c=c,a[o].f=f; a[o].next=head[u],head[u]=o++; a[o].u=v,a[o].v=u,a[o].c=-c,a[o].f=0;//建立反边 a[o].next=head[v],head[v]=o++; } int spfa() { int i,u,v; memset(visit,0,sizeof(visit)); memset(pre,-1,sizeof(pre)); for(i=0; i<=t; i++) dis[i]=inf; queue<int>q; while(!q.empty()) q.pop(); q.push(s); visit[s]=1; dis[s]=0; while(!q.empty()) { u=q.front(); q.pop(); for(i=head[u]; i!=-1; i=a[i].next) { v=a[i].v; if(a[i].f>0&&dis[u]+a[i].c<dis[v]) { dis[v]=dis[u]+a[i].c; pre[v]=i; if(!visit[v]) { visit[v]=1; q.push(v); } } } visit[u]=0; } if(dis[t]==inf) return 0; return 1; } void Add()//修改残留网络 { int i; int mm=inf; for(i=pre[t]; a[i].u!=s; i=pre[a[i].u])//找到最小可增流 mm=min(mm,a[i].f); for(i=pre[t]; a[i].u!=s; i=pre[a[i].u]) { a[i].f-=mm; a[i^1].f+=mm;//修改 maxflow+=mm*a[i].c;//加到maxflow中 } } int main() { int T,i,j,x; cin>>T; while(T--) { cin>>n>>m; o=0; maxflow=0; memset(head,-1,sizeof(head)); for(i=1; i<=n; i++) for(j=1; j<=m; j++) cin>>map[i][j]; for(i=1; i<=n; i++) for(j=1; j<=m; j++) { x=(i-1)*m+j-1; add(2*x,2*x+1,-map[i][j],1);//拆点构图,费用置为负 add(2*x,2*x+1,0,1); } for(i=1; i<=n; i++) for(j=1; j<m; j++)//向右边建图 { x=(i-1)*m+j-1; add(2*x+1,2*(x+1),0,2); } for(i=1; i<n; i++) for(j=1; j<=m; j++)//向下边建图 { x=(i-1)*m+j-1; add(x*2+1,2*(x+m),0,2); } s=n*m*2; t=n*m*2+1; add(s,0,0,2); add(n*m*2-1,t,0,2);//连接源点汇点 while(spfa()) Add(); cout<<-maxflow<<endl; } }
这里再贴出poj 3422 题目连接:点击打开链接
题意上面说过了
代码:
#include<iostream>//和上面那题对比,这个是个n*n的 建图时好建,然后拆点,一条边流量为1,另一条为k-1 #include<cstring> #include<queue> using namespace std; #define M 5050 #define N 100000 #define inf 0x7ffffff struct node { int u,v,c,f,next; } a[N]; int head[M]; int visit[M]; int pre[M]; int dis[M]; int s,t,maxflow,num,k,n; void add(int u,int v,int c,int f) { a[num].u=u; a[num].v=v; a[num].f=f; a[num].c=c; a[num].next=head[u]; head[u]=num++; a[num].u=v; a[num].v=u; a[num].f=0; a[num].c=-c; a[num].next=head[v]; head[v]=num++; } int spfa() { memset(pre,-1,sizeof(pre)); memset(visit,0,sizeof(visit)); for(int i=0; i<=t; i++) dis[i]=inf; dis[s]=0; queue<int>q; visit[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u]; i!=-1; i=a[i].next) { int v=a[i].v; if(a[i].f>0&&dis[u]+a[i].c<dis[v]) { dis[v]=dis[u]+a[i].c; pre[v]=i; if(!visit[v]) { visit[v]=1; q.push(v); } } } visit[u]=0; } if(dis[t]==inf) return 0; return 1; } void Add() { int v; int mm=inf; for(v=pre[t]; a[v].u!=s; v=pre[a[v].u]) mm=min(mm,a[v].f); for(v=pre[t]; a[v].u!=s; v=pre[a[v].u]) { a[v].f-=mm; a[v^1].f+=mm; maxflow+=mm*a[v].c; } } int map[100][100]; int main() { while(cin>>n>>k) { maxflow=0; s=n*n*2; t=s+1; num=0; memset(head,-1,sizeof(head)); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) cin>>map[i][j]; for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { int b=(i-1)*n+j-1; add(b*2,2*b+1,-map[i][j],1); add(b*2,b*2+1,0,k-1); } for(int i=1; i<=n; i++) for(int j=1; j<n; j++) { int b=(i-1)*n+j-1; add(2*b+1,2*(b+1),0,k); } for(int i=1; i<n; i++) for(int j=1; j<=n; j++) { int b=(i-1)*n+j-1; add(b*2+1,2*(b+n),0,k); } add(s,0,0,k); add(n*n*2-1,t,0,k); while(spfa()) Add(); cout<<-maxflow<<endl; } }