FJOI2020 D1T1


题目大意

给出一个由 $n$ 行 $m$ 列的点构成的网格,其中第 $1$ 行,第 $n$ 行,第 $1$ 列与第 $m$ 列为边界,给出 $s$ 个点,求这 $s$ 个点到边界的最小的路径长度之和,要求路径不能交叉。 $n*m\leq20000$。

思路分析

可以看出这是个费用流模板题。根据实测,本题数据卡 EK 单路增广,只能拿到 $70$ 分,需要多路增广才能过。虽然多路增广理论复杂度相同,但是本题中每次增广只能增加 $1$ 的流量,多路增广的确可以提高一定的效率。

#include<iostream>
#include<cstdio>
#include<queue>
#define ano ((i-1)^1)+1
using namespace std;
const int N=1e6+100,INF=0x7f7f7f7f;
int n,m,S,tot,s,t,f,ans;
int head[N],ver[2*N],Next[2*N],edge[2*N],cost[2*N];
int minf[N],pre[N],d[N];
bool v[N];
void add(int x,int y,int z,int c)
{
ver[++tot]=y,edge[tot]=z,cost[tot]=c,Next[tot]=head[x],head[x]=tot;
ver[++tot]=x,edge[tot]=0,cost[tot]=-c,Next[tot]=head[y],head[y]=tot;
}
bool spfa()
{
for(int i=0;i<=t;i++)
d[i]=INF,v[i]=0;
queue<int> q;
q.push(s);
v[s]=1,d[s]=0,minf[s]=INF;
while(q.size())
{
int x=q.front();q.pop();v[x]=0;
for(int i=head[x];i;i=Next[i])
{
if(!edge[i])
continue;
int y=ver[i];
if(d[x]+cost[i]<d[y])
{
d[y]=d[x]+cost[i];
minf[y]=min(minf[x],edge[i]);
pre[y]=i;
if(!v[y])
{
v[y]=1;
q.push(y);
}
}
}
}
return d[t]!=INF;
}/*
void update()
{
int x=t;
while(x!=s)
{
int i=pre[x];
edge[i]-=minf[t];
edge[ano]+=minf[t];
x=ver[ano];
}
f+=minf[t];
ans+=d[t]*minf[t];
}*///单路增广
int dinic(int x,int flow)
{
if(x==t)
return flow;
v[x]=1;
int rest=flow,use;
for(int i=head[x];i && rest;i=Next[i])
{
int y=ver[i];
if(v[y] || !edge[i] || d[y]!=d[x]+cost[i])
continue;
use=dinic(y,min(rest,edge[i]));
if(!use)
d[y]=0;
edge[i]-=use,edge[ano]+=use,rest-=use;
ans+=cost[i]*use;
}
return flow-rest;
}
int id(int x,int y,int z)
{
return (x-1)*m+y+z*n*m;
}
void clear()
{
t=2*n*m+1,ans=tot=f=0;
for(int i=0;i<=t;i++)
head[i]=pre[i]=minf[i]=0;
}
int main()
{
//freopen("covid.in", "r", stdin);
//freopen("covid.out", "w", stdout);
while(scanf("%d%d%d",&n,&m,&S)!=EOF)
{
clear();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
add(id(i,j,0),id(i,j,1),1,0);
if(i!=1)
add(id(i,j,1),id(i-1,j,0),1,1);
if(i!=n)
add(id(i,j,1),id(i+1,j,0),1,1);
if(j!=1)
add(id(i,j,1),id(i,j-1,0),1,1);
if(j!=m)
add(id(i,j,1),id(i,j+1,0),1,1);
if(i==1 || i==n || j==1 || j==m)
add(id(i,j,1),t,1,0);
}
for(int i=1,x,y;i<=S;i++)
{
scanf("%d%d",&x,&y);
add(s,id(x,y,0),1,0);
}/*
while(spfa())
update();*///单路增广
while(spfa())
{
int flow;
do{
for(int i=0;i<=t;i++)
v[i]=0;
flow=dinic(s,INF);
f+=flow;
}while(flow);
}
if(f==S)
printf("%d\n",ans);
else
puts("-1");
}
return 0;
}

[FJOI2020]世纪大逃亡 题解的更多相关文章

  1. HDU 1253 胜利大逃亡 题解

    胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  2. Hdoj 1253.胜利大逃亡 题解

    Problem Description Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会. 魔王住在一个城堡里,城堡是一个ABC的立方体,可以被表示成A个B*C的矩 ...

  3. hdoj 1253 胜利大逃亡

    胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  4. 胜利大逃亡(续)(状态压缩bfs)

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  5. 胜利大逃亡(续)(bfs+状态压缩)

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  6. HDU 3533 Escape(大逃亡)

    HDU 3533 Escape(大逃亡) /K (Java/Others)   Problem Description - 题目描述 The students of the HEU are maneu ...

  7. hdu.1429.胜利大逃亡(续)(bfs + 0101011110)

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  8. 胜利大逃亡[HDU1253]

    胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  9. hdu 1429 胜利大逃亡(续)

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王 ...

随机推荐

  1. PHP imagecolorclosest - 取得与指定的颜色最接近的颜色的索引值

    imagecolorclosest — 取得与指定的颜色最接近的颜色的索引值.高佣联盟 www.cgewang.com 语法 int imagecolorclosest ( resource $ima ...

  2. PHP vprintf() 函数

    实例 输出格式化的字符串: <?php高佣联盟 www.cgewang.com$number = 9;$str = "Beijing";vprintf("There ...

  3. react-router-dom中Switch和exact

    路由地址: 内容: / 根 /user  用户 /user/hh 用户笑了 先说exact:(此时没有Switch),给 / 设置exact精确匹配 地址栏: /user/hh 渲染2个组件 : 用户 ...

  4. 笨办法学python3练习代码ex18.py

    #命名.变量.代码.函数 #this one is like your scripts with argv def print_two(*args): arg1, arg2 = args #将参数解包 ...

  5. Redis服务之集群节点管理

    上一篇博客主要聊了下redis cluster的部署配置,以及使用redis.trib.rb工具所需ruby环境的搭建.使用redis.trib.rb工具创建.查看集群相关信息等,回顾请参考https ...

  6. C#LeetCode刷题-蓄水池抽样

    蓄水池抽样篇 # 题名 刷题 通过率 难度 382 链表随机节点   47.0% 中等 398 随机数索引   41.6% 中等

  7. JavaScript map+parseInt 容易产生的误区

    map /** * 语法: * var new_array = arr.map(function callback(currentValue[,index[,array]]){ * // return ...

  8. golang 标准库

    前言 不做文字搬运工,多做思路整理 就是为了能速览标准库,只整理我自己看过的...... 最好能看看英文的 标准库 fmt strconv string 跳转 golang知识库总结

  9. 图的DFS与BFS

    图的DFS与BFS(C++) 概述 大一学生,作为我的第一篇Blog,准备记录一下图的基本操作:图的创建与遍历.请大佬多多包涵勿喷. 图可以采用邻接表,邻接矩阵,十字链表等多种储存结构进行储存,这里为 ...

  10. 水题大战Vol.3 B. DP搬运工2

    水题大战Vol.3 B. DP搬运工2 题目描述 给你\(n,K\),求有多少个\(1\)到\(n\) 的排列,恰好有\(K\)个数\(i\) 满足\(a_{i-1},a_{i+1}\) 都小于\(a ...