考虑如何建图。还是老样子先拆点,然后把每两个点之间连接两条边,一条流量为1,费用为-点权,处理是否走这个点。一条流量无限,没有费用,因为哪怕一个点选过了,它的地方还是可以重复走过去的。 然后把经由一个点能到达的另一个点连边。因为要走k次,所以由s向1号点入点连边,n号点出点向t连边,流量为k,费用为0。然后一边最小费用最大流板子即可。 然后发现这些个题解里没有用原始对偶来实现的,所以弱弱的拿出自己代码,勉强还是能在最优解第一页里的,膜拜那些50ms都不到就跑完的dalao们。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
#define rp (i-1)*n+j
#define cp (i-1)*n+j+n*n
#define inf 50000000
#define re register
using namespace std;
struct po
{
int from,to,dis,nxt,w;
}edge[];
int head[],cur[],dep[],n,m,s,t,u,num=-,x,y,l,tot,sum,k;
int dis[],b[],xb[],flow[],a[][];
inline int read()
{
int x=,c=;
char ch=' ';
while((ch>''||ch<'')&&ch!='-')ch=getchar();
while(ch=='-')c*=-,ch=getchar();
while(ch<=''&&ch>='')x=x*+ch-'',ch=getchar();
return x*c;
}
inline void add_edge(int from,int to,int w,int dis)
{
edge[++num].nxt=head[from];
edge[num].to=to;
edge[num].w=w;
edge[num].dis=dis;
head[from]=num;
}
inline void add(int from,int to,int w,int dis)
{
add_edge(from,to,w,dis);
add_edge(to,from,,-dis);
}
inline bool spfa()
{
memset(b,,sizeof(b));
memset(dis,,sizeof(dis));
deque<int> q;
while(!q.empty())
q.pop_back();
dis[t]=;b[t]=;
q.push_back(t);
while(!q.empty())
{
int u=q.front();
q.pop_front();
b[u]=;
for(re int i=head[u];i!=-;i=edge[i].nxt)
{
int v=edge[i].to;
if(edge[i^].w>&&dis[v]>dis[u]-edge[i].dis)
{
dis[v]=dis[u]-edge[i].dis;
if(!b[v])
{
b[v]=;
if(!q.empty()&&dis[v]<dis[q.front()])
q.push_front(v);
else
q.push_back(v);
}
}
}
}
return dis[s]<inf;
}
inline int dfs(int u,int low)
{
if(u==t)
{
b[t]=;
return low;
}
int diss=;
b[u]=;
for(re int i=head[u];i!=-;i=edge[i].nxt)
{
int v=edge[i].to;
if(!b[v]&&edge[i].w!=&&dis[v]==dis[u]-edge[i].dis)
{
int check=dfs(v,min(low,edge[i].w));
if(check>)
{
tot+=check*edge[i].dis;
low-=check;
diss+=check;
edge[i].w-=check;
edge[i^].w+=check;
if(low==) break;
}
}
}
return diss;
}
inline void max_flow()
{
int ans=;
while(spfa())
{
b[t]=;
while(b[t]==)
{
memset(b,,sizeof(b));
ans=dfs(s,inf);
}
}
}
int main()
{
memset(head,-,sizeof(head));
n=read();k=read();
for(re int i=;i<=n;i++)
for(re int j=;j<=n;j++)
a[i][j]=read();
s=;t=n*n*+;
add(s,,k,);add(n*n*,t,k,);
for(re int i=;i<=n;i++)
for(re int j=;j<=n;j++)
{
add(rp,cp,,-a[i][j]);
add(rp,cp,inf,);
if(i<n)
add(cp,rp+n,inf,);
if(j<n)
add(cp,rp+,inf,);
}
max_flow();
cout<<-tot;
}

最新文章

  1. Json数组追加数据
  2. Spring中Bean的作用域
  3. web前端之HTML的大框架(body元素与frameset元素)
  4. zoj1260 king
  5. Protobuf从安装到配置整理帖
  6. 使用Powershell在Microsoft Azure中创建Virtual Machine
  7. Java基础知识强化之网络编程笔记04:UDP之发送端的数据来自于键盘录入案例
  8. 【原创】CMD常用命令:解决实际问题
  9. 嵌入式设备web服务器比较
  10. 深入学习Java中的字符串,代码点和代码单元
  11. 使用docker 解决一个小问题,你也可能用的到
  12. 每日冲刺报告-Day4
  13. Fiddler抓取数据并分析(完整的配置教程)
  14. Swoft 图片上传与处理
  15. Docker Kubernetes 创建管理 Deployment
  16. c# webbrowser控件内核版本强制修改
  17. iOS 技术篇:如何处理多个网络请求的先后(依赖)关系
  18. (转)mybatis数据库物理分页插件PageHelper
  19. C# null,string.Empty,&quot;&quot;,DBNull 的区别
  20. Ionic 自动创建应用的图标与启动画面

热门文章

  1. SAP FI 中4个特殊期间
  2. python3 - 使用__slots__限制实例属性
  3. 使用jsx语法环境搭建
  4. 集成 SOLR 到 TOMCAT 中(傻瓜教程)
  5. [Spring Framework]学习笔记--Dependency injection(DI)
  6. C++ 基础知识回顾(string基础、智能指针、迭代器、容器类)
  7. oracle 查看表是否被锁
  8. 你意识到苹果公司已经抛弃了GC吗?
  9. The JVM found at JAVA_HOME is damaged.Please reinstall or define EXE4J_JAVA_HOME to point to an installed 32-bit JDK or JRE
  10. 004-RIP、OSPF【路由选择协议】