【BZOJ 1001:[BeiJing2006]狼抓兔子 最小割转对偶图堆优化dij
来源:互联网 发布:ros系统 与 linux 编辑:程序博客网 时间:2024/06/08 00:43
1001: [BeiJing2006]狼抓兔子
Time Limit: 15 Sec Memory Limit: 162 MB
Submit: 23509 Solved: 5914
[Submit][Status][Discuss]
Description
现在小朋友们最喜欢的”喜羊羊与灰太狼”,话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路
1:(x,y)<==>(x+1,y)
2:(x,y)<==>(x,y+1)
3:(x,y)<==>(x+1,y+1)
道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14
思路:首先第一感是裸的最大流,但数据范围很明显不允许这么做,这样只能过部分的点。
那么考虑其他做法,发现这个网格图实际上是一个对偶图,我们要求最大流也就是求最小割,那么最小割也可以看成一个割掉边的边,那么就可以看成连接一条边两侧的一条边。设置一个超级汇点和超级源点,跑一边spfa或者堆优化dij即可,注意堆优化dij别打残。
参考[知识点]网络流之转换对偶图
及参考2006年集训队论文 《浅析最大最小定理在信息学竞赛中的应用》周冬
部分分最大流做法:
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#define inf 1e9#define MAXN 10005using namespace std;queue<int> q;struct node{ int to,remain,next;}e[MAXN];int e_num=-1,point[MAXN];int deep[MAXN],cur[MAXN];bool vis[MAXN];int s,t,ans,n,m;void add(int from,int to,int remain){ ++e_num; e[e_num].to=to; e[e_num].remain=remain; e[e_num].next=point[from]; point[from]=e_num;}bool bfs(int from,int to){ memset(deep,0x7f,sizeof(deep)); memset(vis,0,sizeof(vis)); for (int i=1;i<=n*m+1;i++) cur[i]=point[i]; deep[from]=0; vis[from]=1; q.push(from); while (!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for (int i=point[u];i!=-1;i=e[i].next) if (deep[e[i].to]>inf&&e[i].remain) { deep[e[i].to]=deep[u]+1; if (!vis[e[i].to]) { q.push(e[i].to); vis[e[i].to]=true; } } } return deep[to]<inf;} int dfs(int from,int to,int limit){ int f,flow=0; if (!limit) return 0; if (from==to) return limit; for (int i=cur[from];i!=-1;i=e[i].next) { cur[from]=i; if (deep[e[i].to]==deep[from]+1&&(f=dfs(e[i].to,to,min(limit,e[i].remain)))) { flow+=f; limit-=f; e[i].remain-=f; e[i^1].remain+=f; if (!limit) break; } } return flow;}void dinic(){ while (bfs(s,t)) ans+=dfs(s,t,inf);}int main(){ freopen("bjrabbit.in","r",stdin); freopen("bjrabbit.out","w",stdout); int x; memset(point,-1,sizeof(point)); scanf("%d%d",&n,&m); s=1;t=n*m; for (int i=1;i<=n;i++) for (int j=1;j<=m-1;j++) { scanf("%d",&x); add((i-1)*m+j,(i-1)*m+j+1,x); add((i-1)*m+j+1,(i-1)*m+j,0); add((i-1)*m+j+1,(i-1)*m+j,x); add((i-1)*m+j,(i-1)*m+j+1,0); } for (int i=1;i<=n-1;i++) for (int j=1;j<=m;j++) { scanf("%d",&x); add((i-1)*m+j,i*m+j,x); add(i*m+j,(i-1)*m+j,0); add(i*m+j,(i-1)*m+j,x); add((i-1)*m+j,i*m+j,0); } for (int i=1;i<=n-1;i++) for (int j=1;j<=m-1;j++) { scanf("%d",&x); add((i-1)*m+j,i*m+j+1,x); add(i*m+j+1,(i-1)*m+j,0); add(i*m+j+1,(i-1)*m+j,x); add((i-1)*m+j,i*m+j+1,0); } dinic(); printf("%d",ans);}
满分对偶图做法:
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#define inf 1e9#define MAXN 2000005using namespace std;struct bian{ int to,dis,next;}e[MAXN];struct node{ int dis,id; friend bool operator < (node a,node b) { return a.dis > b.dis; }};int point[MAXN],e_num,cc[MAXN+100];int s,t,n,m;bool flag[MAXN];inline void add(int from,int to,int dis){ e_num++; e[e_num].to=to; e[e_num].dis=dis; e[e_num].next=point[from]; point[from]=e_num;}void dij(){ for (int i=0;i<=MAXN;i++) cc[i]=inf; memset(flag,false,sizeof(flag)); cc[s]=0; priority_queue<node> q; node now; now.id=s,now.dis=0; q.push(now); while (!q.empty()) { now=q.top(); q.pop(); if (flag[now.id]==true) continue; flag[now.id]=true; int x=now.id; for (int i=point[x];i;i=e[i].next) { if (cc[x]+e[i].dis<cc[e[i].to]) { cc[e[i].to]=cc[x]+e[i].dis; now.id=e[i].to; now.dis=cc[e[i].to]; q.push(now); } } }}int main(){ freopen("bjrabbit.in","r",stdin); freopen("bjrabbit.out","w",stdout); int x; scanf("%d%d",&n,&m); s=0;t=(n-1)*(m-1)+10; for (int i=1;i<=n;i++) for (int j=1;j<=m-1;j++) { scanf("%d",&x); if (i==1) add(s,j,x),add(j,s,x); else if (i==n) add((i*2-3)*(m-1)+j,t,x),add(t,(i*2-3)*(m-1)+j,x); else { add(((i-1)*2-1)*(m-1)+j,((i-1)*2-1)*(m-1)+j+(m-1),x); add(((i-1)*2-1)*(m-1)+j+(m-1),((i-1)*2-1)*(m-1)+j,x); } } for (int i=1;i<=n-1;i++) for (int j=1;j<=m;j++) { scanf("%d",&x); if (j==1) add(t,(i*2-1)*(m-1)+j,x),add((i*2-1)*(m-1)+j,t,x); else if (j==m) add(s,(i*2-1)*(m-1),x),add((i*2-1)*(m-1),s,x); else { add((i-1)*2*(m-1)+j-1,(i-1)*2*(m-1)+j-1+m,x); add((i-1)*2*(m-1)+j-1+m,(i-1)*2*(m-1)+j-1,x); } } for (int i=1;i<=n-1;i++) for (int j=1;j<=m-1;j++) { scanf("%d",&x); add((i-1)*2*(m-1)+j,(i-1)*2*(m-1)+j+(m-1),x); add((i-1)*2*(m-1)+j+(m-1),(i-1)*2*(m-1)+j,x); } dij(); printf("%d",cc[t]);}
- 【BZOJ 1001:[BeiJing2006]狼抓兔子 最小割转对偶图堆优化dij
- bzoj 1001: [BeiJing2006]狼抓兔子 对偶图最短路-(最小割)
- 【BZOJ1001】【Beijing2006】狼抓兔子(平面图转对偶图:最小割+最短路)
- bzoj 1001: [BeiJing2006]狼抓兔子(最小割)
- Bzoj 1001: [BeiJing2006]狼抓兔子(最小割)
- bzoj。1001: [BeiJing2006]狼抓兔子 (最小割)
- BZOJ 1001: [BeiJing2006]狼抓兔子 对偶图
- bzoj 1001: [BeiJing2006]狼抓兔子 最短路+对偶图
- BZOJ-1001 狼抓兔子 (最小割-最大流)平面图转对偶图+SPFA
- 【BZOJ1001】[BeiJing2006]狼抓兔子【最小割】【最短路】【对偶图】
- [最小割+对偶建图+最短路] BZOJ1001: [BeiJing2006]狼抓兔子
- 【最小割+对偶图=最短路】BZOJ1001 [BeiJing2006]狼抓兔子
- bzoj1001 [BeiJing2006]狼抓兔子(最小割/平面图最大流转对偶图最短路)
- BZOJ1001: [BeiJing2006]狼抓兔子 (最小割)
- [BeiJing2006]狼抓兔子 平面图最小割
- BZOJ 1001([BeiJing2006]狼抓兔子-最大流转对偶图最短路)
- [BZOJ1001]Beijing2006 狼抓兔子|平面图转对偶图
- BZOJ 1001[BeiJing2006]狼抓兔子 最小割转最短路
- Windows下使用SSD检测
- recycler 的adapter 的点击事件
- 将博客搬至CSDN
- django学习之路(一)
- 交叉编译,使用迭代器造成编译失败;
- 【BZOJ 1001:[BeiJing2006]狼抓兔子 最小割转对偶图堆优化dij
- gtest学习笔记
- 斐波那契数列算法优化问题
- 2017年全国大学生电子设计竞赛 猜题了
- SVN相关概念及操作
- C++类成员的访问权限
- linux编程---IO复用---select
- Fleury算法求欧拉路径
- POJ1486 Sorting Slides【二分匹配】