BZOJ 1001: [BeiJing2006]狼抓兔子
2014-03-15 17:03
387 查看
题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1001
题目大意:见原题&算法讨论。
算法讨论:
很容易看出这是最小割。
我们首先想到的是最小割=最大流。
但是点数最多有1e6,用O(n^2*m)的Dinic和O(n*m^2)的sap显然都是要超时的。(据说Dinic也能过?)
于是我们想到了另一个公式:平面图最大流=对偶图最短路。
网格图做对偶图是很方便的啦~
然后SPFA就更方便了啦~
Code:
/*
* Problem:1001
* Author:PYC
*/
#include <cstdio>
#define Vnum (1000*1000*2)
#define Enum (1000*1000*5*2)
#define maxn 2000100
#define oo (1<<30)
#define Bnum 1100
#define ooo 2147483647
using namespace std;
int n,m,mm,son[Vnum],next[Enum],ed[Enum],data[Enum],end,h=0,t=1,q[maxn],dis[maxn],tt=1,id[Bnum][Bnum][2];
bool v[maxn];
inline int min(int x,int y){
return x<y?x:y;
}
inline void INSERT(int x,int y,int z){
mm++;
next[mm]=son[x];
son[x]=mm;
ed[mm]=y;
data[mm]=z;
}
inline void insert(int x,int y,int z){
INSERT(x,y,z);
INSERT(y,x,z);
}
void spfa(){
for (int i=2;i<=end;++i) dis[i]=oo;
v[1]=1;
q[1]=1;
while (h!=t){
h++;
h%=maxn;
v[q[h]]=0;
int x=q[h];
for (int i=son[x];i;i=next[i]){
int y=ed[i];
if (dis[x]+data[i]<dis[y]){
dis[y]=dis[x]+data[i];
if (!v[y]){
t++;
t%=maxn;
v[y]=1;
q[t]=y;
}
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
if (n==1 && m==1){
printf("0\n");
return 0;
}
if (n==1){
int ans=ooo;
for (int i=1;i<=m-1;++i){
int x;
scanf("%d",&x);
ans=min(ans,x);
}
printf("%d\n",ans);
return 0;
}
if (m==1){
int ans=ooo;
for (int i=1;i<=n-1;++i){
int x;
scanf("%d",&x);
ans=min(ans,x);
}
printf("%d\n",ans);
return 0;
}
for (int i=1;i<=n-1;++i)
for (int j=1;j<=m-1;++j){
++tt;
id[i][j][0]=tt;
++tt;
id[i][j][1]=tt;
}
end=tt+1;
for (int i=1;i<=n;++i)
for (int j=1;j<=m-1;++j){
int x;
scanf("%d",&x);
if (i==1){
insert(1,id[i][j][0],x);
continue;
}
if (i==n){
insert(end,id[i-1][j][1],x);
continue;
}
insert(id[i][j][0],id[i-1][j][1],x);
}
for (int i=1;i<=n-1;++i)
for (int j=1;j<=m;++j){
int x;
scanf("%d",&x);
if (j==1){
insert(end,id[i][j][1],x);
continue;
}
if (j==m){
insert(1,id[i][j-1][0],x);
continue;
}
insert(id[i][j-1][0],id[i][j][1],x);
}
for (int i=1;i<=n-1;++i)
for (int j=1;j<=m-1;++j){
int x;
scanf("%d",&x);
insert(id[i][j][0],id[i][j][1],x);
}
spfa();
printf("%d\n",dis[end]);
return 0;
}
By Charlie Pan
Mar 15,2014
题目大意:见原题&算法讨论。
算法讨论:
很容易看出这是最小割。
我们首先想到的是最小割=最大流。
但是点数最多有1e6,用O(n^2*m)的Dinic和O(n*m^2)的sap显然都是要超时的。(据说Dinic也能过?)
于是我们想到了另一个公式:平面图最大流=对偶图最短路。
网格图做对偶图是很方便的啦~
然后SPFA就更方便了啦~
Code:
/*
* Problem:1001
* Author:PYC
*/
#include <cstdio>
#define Vnum (1000*1000*2)
#define Enum (1000*1000*5*2)
#define maxn 2000100
#define oo (1<<30)
#define Bnum 1100
#define ooo 2147483647
using namespace std;
int n,m,mm,son[Vnum],next[Enum],ed[Enum],data[Enum],end,h=0,t=1,q[maxn],dis[maxn],tt=1,id[Bnum][Bnum][2];
bool v[maxn];
inline int min(int x,int y){
return x<y?x:y;
}
inline void INSERT(int x,int y,int z){
mm++;
next[mm]=son[x];
son[x]=mm;
ed[mm]=y;
data[mm]=z;
}
inline void insert(int x,int y,int z){
INSERT(x,y,z);
INSERT(y,x,z);
}
void spfa(){
for (int i=2;i<=end;++i) dis[i]=oo;
v[1]=1;
q[1]=1;
while (h!=t){
h++;
h%=maxn;
v[q[h]]=0;
int x=q[h];
for (int i=son[x];i;i=next[i]){
int y=ed[i];
if (dis[x]+data[i]<dis[y]){
dis[y]=dis[x]+data[i];
if (!v[y]){
t++;
t%=maxn;
v[y]=1;
q[t]=y;
}
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
if (n==1 && m==1){
printf("0\n");
return 0;
}
if (n==1){
int ans=ooo;
for (int i=1;i<=m-1;++i){
int x;
scanf("%d",&x);
ans=min(ans,x);
}
printf("%d\n",ans);
return 0;
}
if (m==1){
int ans=ooo;
for (int i=1;i<=n-1;++i){
int x;
scanf("%d",&x);
ans=min(ans,x);
}
printf("%d\n",ans);
return 0;
}
for (int i=1;i<=n-1;++i)
for (int j=1;j<=m-1;++j){
++tt;
id[i][j][0]=tt;
++tt;
id[i][j][1]=tt;
}
end=tt+1;
for (int i=1;i<=n;++i)
for (int j=1;j<=m-1;++j){
int x;
scanf("%d",&x);
if (i==1){
insert(1,id[i][j][0],x);
continue;
}
if (i==n){
insert(end,id[i-1][j][1],x);
continue;
}
insert(id[i][j][0],id[i-1][j][1],x);
}
for (int i=1;i<=n-1;++i)
for (int j=1;j<=m;++j){
int x;
scanf("%d",&x);
if (j==1){
insert(end,id[i][j][1],x);
continue;
}
if (j==m){
insert(1,id[i][j-1][0],x);
continue;
}
insert(id[i][j-1][0],id[i][j][1],x);
}
for (int i=1;i<=n-1;++i)
for (int j=1;j<=m-1;++j){
int x;
scanf("%d",&x);
insert(id[i][j][0],id[i][j][1],x);
}
spfa();
printf("%d\n",dis[end]);
return 0;
}
By Charlie Pan
Mar 15,2014
相关文章推荐
- CSU1307 并查集+SPFA
- USACO/butter 3.2.6
- hdu 1596 find the safest road(spfa算法)
- [bzoj1003] [ZJOI2006]物流运输trans
- [bzoj1500][NOI2005]维修数列
- [bzoj1208] [HNOI2004]宠物收养所
- [bzoj1269][AHOI2006]文本编辑器editort
- [bzoj1503][NOI2004]郁闷的出纳员
- BZOJ 3180 coci2012 ograda
- [网络流24题 #18]分配问题
- [网络流24题 #18]分配问题
- bzoj 1801: [Ahoi2009] chess 中国象棋
- bzoj 1717: [Usaco2006 Dec] Milk Patterns
- bzoj 1027: [JSOI2007] 合金
- bzoj 2298: [HAOI2011]problem a
- 【SDOI2011】【BZOJ】【P2241】【打地鼠】【题解】
- 【SDOI2011】【BZOJ】【P2242】【计算器】【题解】【快速幂+扩展欧几里得+高次同余方程/BSGS】
- 【SDOI2013】【BZOJ】【P3122】【随机数生成器】【Baby Step Giant Step】
- 【SDOI2008】【BZOJ】【P2190】【仪仗队】【题解】
- 【SDOI2008】【BZOJ】【P2037】【Sue的小球】【题解】【费用提前计算相关的DP】