题目链接:传送门

题目大意:给你一个矩阵,每个格子有一个值,现在你要从左上角走到右下角(走3次),使得经过路径的权值和最大。

     每个格子的值只能取一次,取完后变为0,输出走完三次后最大的权值和。

题目思路:费用流做法,对于每个格子拆点,因为权值只有第一次能取,所以将每个格子拆为两条边,一条边容量为1,费用为格子的权值,另一条边容量2,费用0。

     相邻格子间连边,容量3,费用0。再建立源点S 与左上角第一个格子连边容量3,费用0。汇点 T 与右下角最后一个格子连边,容量3,费用0。跑费用流累加费用即可。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cctype>
#include <queue>
#include <string>
#include <vector>
#include<functional>
#include <set>
#include <map>
#include <climits>
#define lson root<<1,l,mid
#define rson root<<1|1,mid+1,r
#define fi first
#define se second
#define ping(x,y) ((x-y)*(x-y))
#define mst(x,y) memset(x,y,sizeof(x))
#define mcp(x,y) memcpy(x,y,sizeof(y))
using namespace std;
#define gamma 0.5772156649015328606065120
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define N 100005
#define maxn 10005
typedef pair<int,int> PII;
typedef long long LL; int n,m,ans,S,T,cost;
char pic[][];
int num[][];
int vis[maxn],pre[maxn],d[maxn];
struct Node{
int to,next,f,c;
Node(){}
Node(int a,int b,int _c,int d):to(a),next(b),f(_c),c(d){}
}node[N];int head[maxn],hcnt;
queue<int>q;
inline void add(int x,int y,int f,int c){
node[hcnt]=Node(y,head[x],f,c);head[x]=hcnt++;
node[hcnt]=Node(x,head[y],,-c);head[y]=hcnt++;
}
void init(){
mst(head,-);hcnt=;
S=;T=n*n*+;
add(S,,,);add(num[n][n]+n*n,T,,);
for(int i=;i<=n;++i)for(int j=;j<=n;++j){
if(i+<=n)add(num[i][j]+n*n,num[i+][j],,);
if(j+<=n)add(num[i][j]+n*n,num[i][j+],,);
add(num[i][j],num[i][j]+n*n,,);
add(num[i][j],num[i][j]+n*n,,pic[i][j]-'');
}
}
int spfa(){
pre[S]=pre[T]=-;
mst(vis,);mst(d,-);d[S]=;
q.push(S);
while(!q.empty()){
int x=q.front();q.pop();
vis[x]=;
for(int i=head[x];~i;i=node[i].next){
int e=node[i].to;
if(node[i].f&&d[e]<d[x]+node[i].c){
pre[e]=i^;
d[e]=d[x]+node[i].c;
if(!vis[e]){
q.push(e);
vis[e]=;
}
}
}
}
return pre[T]!=-;
}
void mcmf(){
init();
while(spfa()){
int fl=inf;
for(int i=pre[T];~i;i=pre[node[i].to])
fl=min(fl,node[i^].f);
for(int i=pre[T];~i;i=pre[node[i].to]){
node[i].f+=fl;node[i^].f-=fl;
}
cost+=d[T];
}
printf("%d\n",cost);
}
int main() {
int i,j,group,x,y,Case=;
scanf("%d",&n);
for(i=;i<=n;++i){
scanf("%s",pic[i]+);
for(j=;j<=n;++j)
num[i][j]=++Case;
}
mcmf();
return ;
}

    

最新文章

  1. FreeBSD_11-系统管理——{Part_8 - IPFW}
  2. Objective-c 代理模式(delegate)
  3. .ipynb文件 与ipython notebook
  4. Stanford机器学习---第八讲. 支持向量机SVM
  5. Xshell 中文乱码
  6. python pdb
  7. WPF让人哭笑不得的资源
  8. ZOJ 2314 带上下界的可行流
  9. SQL中binary 和 varbinary的区别 blob
  10. Elasticsearch学习1--head插件安装
  11. 关于map
  12. Java EE基础之JSP(二)
  13. Java容器的各种总结
  14. 编写高质量代码改善程序的157个建议:使用Dynamic来简化反射的实现
  15. c3p0使用记录
  16. 2018/1/28 每日一学 单源最短路的SPFA算法以及其他三大最短路算法比较总结
  17. 2015年北京的第一场雪-关于android学习的思考(84)
  18. nodejs-QQ空间灌水
  19. Netcat实用操作
  20. Python 类的祖宗--metaclass

热门文章

  1. 学习-短信的上行(MO)和下行(MT)详解
  2. C#调用Windows CMD命令并,返回输出结果或错误信息
  3. FIFO、LRU、OPT页面调度算法及样例
  4. 兼容placeholder
  5. C语言printf格式化输出修饰符详解
  6. php处理XML数据
  7. Atitit.jpg png格式差别以及解决jpg图片不显示的问题
  8. Atitit.swt&#160;线程调用ui控件的方法
  9. 品茗论道说广播(Broadcast内部机制讲解)(下)
  10. InnoDB:表