对偶图及其应用
来源:互联网 发布:ubuntu kylin 安装jdk 编辑:程序博客网 时间:2024/06/05 22:48
对偶图及其应用
模型
每个平面图
G∗ 中的每个点对应G 中的一个面- 对于
G 中的,每条边e e 属于两个面f1,f2 ,加入边(f∗1,f∗2) e 只属于一个面f ,加入回边(f∗,f∗)
(图中加入了个绿色边围成的面,需要删除
这样我们通过求
分析一下时间复杂度:
- 直接用 Dinic 求最大流:
O(EV2) - 最大流转化最短路,用堆优化 Dijkstra :
O(Vlog2V)
明显快了很多,然而实际跑起来差别并不大:
主要原因是 Dinic 加了优化之后时间复杂度很玄学……
题目
[bzoj1001]狼抓兔子[BeiJing2006]
Time Limit: 15 Sec Memory Limit: 162 MB
题目描述
现在小朋友们最喜欢的”喜羊羊与灰太狼”,话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(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只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
输入格式
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
输出格式
输出一个整数,表示参与伏击的狼的最小数量.
样例输入
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
样例输出
14
本题就是一到十分经典的用对偶图将最大流转化为最短路的题。
解题思路与之前讲的十分相似,只是建图比较麻烦,需要注意;还有一点就是当
最大流
#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int MAXV=1e6+5,MAXE=3e6+5,INF=~0U>>1;//6int N,M,S,T;struct E{int next,to,cap;} e[MAXE<<2];int ecnt=1,G[MAXV];void addEdge(int u,int v,int c){ e[++ecnt]=(E){G[u],v,c};G[u]=ecnt; e[++ecnt]=(E){G[v],u,0};G[v]=ecnt;}int dfn[MAXV];queue<int> que;bool calDfn(){ int i; memset(dfn,-1,sizeof(dfn)); dfn[S]=0;que.push(S); while(!que.empty()) { int u=que.front();que.pop(); for(i=G[u];i;i=e[i].next) { int v=e[i].to; if(e[i].cap>0&&dfn[v]==-1) dfn[v]=dfn[u]+1,que.push(v); } } return dfn[T]!=-1;}int iter[MAXV];int calF(int u,int f){ if(u==T) return f; for(int & i=iter[u];i;i=e[i].next) { int v=e[i].to; if(e[i].cap>0&&dfn[v]==dfn[u]+1) { int res=calF(v,min(f,e[i].cap)); if(res>0) { e[i].cap-=res,e[i^1].cap+=res; return res; } } } return 0;}int dinic(){ int i,f,res=0; while(calDfn()) { for(i=1;i<=N*M;i++) iter[i]=G[i]; while((f=calF(S,INF))>0) res+=f; } return res;}int main(){ int i,j,u,v,c; scanf("%d%d",&N,&M); S=1,T=N*M; for(i=1;i<=N;i++) for(j=1;j<M;j++) { u=j+(i-1)*M,v=u+1;scanf("%d",&c); addEdge(u,v,c);addEdge(v,u,c); } for(i=1;i<N;i++) for(j=1;j<=M;j++) { u=j+(i-1)*M,v=u+M;scanf("%d",&c); addEdge(u,v,c);addEdge(v,u,c); } for(i=1;i<N;i++) for(j=1;j<M;j++) { u=j+(i-1)*M,v=u+M+1;scanf("%d",&c); addEdge(u,v,c);addEdge(v,u,c); } printf("%d\n",dinic()); return 0;}
最短路
#include<iostream>#include<cstdio>#include<queue>using namespace std;const int MAXV=2e6+105,MAXE=3e6+5,INF=~0U>>1;int N,M,S,T;struct E{int next,to,val;} e[MAXE<<1];int ecnt,G[MAXV];void addEdge(int u,int v,int w)//双向边{ e[++ecnt]=(E){G[u],v,w};G[u]=ecnt; e[++ecnt]=(E){G[v],u,w};G[v]=ecnt;}struct HN{ int id,v; bool operator<(const HN & ot)const {return v>ot.v;}};priority_queue<HN> heap;bool inS[MAXV];int dis[MAXV];int dijkstra(){ int i; for(i=1;i<=T;i++) dis[i]=INF; dis[S]=0;heap.push((HN){S,0}); while(!heap.empty()) { int u=heap.top().id;heap.pop(); if(inS[u]) continue; inS[u]=true; for(i=G[u];i;i=e[i].next) { int v=e[i].to; if(inS[v]) continue; if(dis[v]>dis[u]+e[i].val) { dis[v]=dis[u]+e[i].val; heap.push((HN){v,dis[v]}); } } } return dis[T];}int main(){ int i,j,w; scanf("%d%d",&N,&M); if(N==1||M==1) { if(N>M) swap(N,M); int ans=INF; for(i=1;i<=M;i++) scanf("%d",&w),ans=min(ans,w); printf("%d\n",ans); }else { S=2*(N-1)*(M-1)+1,T=S+1; //读取横向 for(i=1;i<M;i++) {int v=i*2;scanf("%d",&w);addEdge(S,v,w);} for(i=2;i<N;i++) for(j=1;j<M;j++) {int u=2*((i-2)*(M-1)+j)-1,v=2*((i-1)*(M-1)+j);scanf("%d",&w);addEdge(u,v,w);} for(i=1;i<M;i++) {int u=2*((N-2)*(M-1)+i)-1;scanf("%d",&w);addEdge(u,T,w);} //读取纵向 for(i=1;i<N;i++) for(j=1;j<=M;j++) { scanf("%d",&w); if(j==1) {int u=2*((i-1)*(M-1)+j)-1;addEdge(u,T,w);} else if(j==M) {int v=2*((i-1)*(M-1)+j-1);addEdge(S,v,w);} else {int u=2*((i-1)*(M-1)+j-1),v=u+1;addEdge(u,v,w);} } //读取斜向 for(i=1;i<N;i++) for(j=1;j<M;j++) {int u=2*((i-1)*(M-1)+j)-1,v=u+1;scanf("%d",&w);addEdge(u,v,w);} printf("%d\n",dijkstra()); } return 0;}/* * --------- * |1\2|3\4| * |---|---| * |5\6|7\8| * |---|---| */
- 对偶图及其应用
- 对偶图的应用
- 感知机模型及其对偶形式
- 优化问题及其Lagrange对偶问题
- 图及其应用
- 圆图及其应用
- 图算法及其应用
- 图结构及其应用
- 概率图模型(06): 概率图双重对偶视角 || 马尔可夫网 & 条件随机场及应用
- 对偶原理在SVM中的应用
- 【网络流】【对偶图】海拔
- bzoj1001 平面图转对偶图
- 感知机及其对偶问题,参考《统计学习方法》
- 图遍历算法及其应用
- 拉格朗日对偶问题,以及在SVM中的应用
- 【网络流】【对偶图】【NOI2010】海拔
- [NOI2010] 海拔altitude 最小割 对偶图
- BZOJ1001(对偶图+最短路)
- C#委托的应用
- 待搞清楚知识点
- 项目要点
- 2017-05-11 DBA日记,导致log file sync单次等待超500ms又一可能
- 每天一个Linux命令:rmdir
- 对偶图及其应用
- 一些rtsp实现的开源代码
- 寻找和为定值的数
- 判断一个坐标点是否在不规则多边形内部的算法
- Linux编程基础之进程间通信之二:有名管道
- 【大数据】Knowledge structure
- [Algorithm]九章四:BSF
- 判断一个点是否在任意闭合多边形内
- java学习(12)