【BZOJ1001】【Beijing2006】狼抓兔子(平面图转对偶图:最小割+最短路)
2016-02-24 17:18
411 查看
题目描述
传送门题解
题目描述很明显这就是一道最小割,不过跑最大流的话会TLE。我们发现这是一个平面图(什么是平面图?),那么我们就可以参考平面图转对偶图的思想,将这道题转化成最短路。
可参考资料:对偶图的应用
建图的时候十分的麻烦。。。
代码
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=1005; const int max_m=1005; const int max_N=max_n*max_m*2+5; const int max_e=3*max_n*max_m+5; const int max_queue=max_N*2+5; const int inf=2100000000; int n,m,N,now,nowlast; int heng[max_n][max_m],zong[max_n][max_m],xie[max_n][max_m]; int next[max_e*2],point[max_N],c[max_e*2],v[max_e*2],tot; int dis[max_N],queue[max_queue+5],head,tail; bool b[max_N]; inline void add(int x,int y,int val){ ++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=val; ++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=val; } int main(){ scanf("%d%d",&n,&m); //总点数 N=(n-1)*(m-1)*2+2; //特判 if (n==1&&m==1){ printf("0\n"); return 0; } if (n==1){ int Min=inf,x; for (int i=1;i<m;++i) scanf("%d",&x),Min=min(Min,x); printf("%d\n",Min); return 0; } if (m==1){ int Min=inf,x; for (int i=1;i<n;++i) scanf("%d",&x),Min=min(Min,x); printf("%d\n",Min); return 0; } //read for (int i=1;i<=n;++i) for (int j=1;j<m;++j) scanf("%d",&heng[i][j]); for (int i=1;i<n;++i) for (int j=1;j<=m;++j) scanf("%d",&zong[i][j]); for (int i=1;i<n;++i) for (int j=1;j<m;++j) scanf("%d",&xie[i][j]); //build up for (int i=1;i<n;++i) for (int j=1;j<m;++j){ now=(i-1)*(m-1)+j; //斜向 add(now*2,now*2+1,xie[i][j]); //纵向 if (j!=1) add(now*2-1,now*2,zong[i][j]); //横向 if (i!=1){ nowlast=now-(m-1); add(nowlast*2,now*2+1,heng[i][j]); } } //S for (int i=1;i<n;++i){ now=(i-1)*(m-1)+1; add(1,now*2,zong[i][1]); now=(i-1)*(m-1)+m-1; add(now*2+1,N,zong[i][m]); } //T for (int i=1;i<m;++i){ now=i; add(now*2+1,N,heng[1][i]); now=(n-2)*(m-1)+i; add(1,now*2,heng [i]); } //SPFA memset(dis,0x7f,sizeof(dis)); memset(b,0,sizeof(b)); dis[1]=0; head=0; tail=1; queue[tail]=1; b[1]=true; while (head!=tail){ head++; now=queue[head%max_queue]; b[now]=false; for (int i=point[now];i;i=next[i]) if (dis[v[i]]>dis[now]+c[i]){ dis[v[i]]=dis[now]+c[i]; if (!b[v[i]]){ tail++; queue[tail%max_queue]=v[i]; b[v[i]]=true; } } } printf("%d\n",dis ); }
相关文章推荐
- jni学习简单例子
- Jmeter基础之---jmeter基础概念
- 如何在present出来的viewController里使用push方法
- 卡片游戏
- Invalid Bundle. iPad multimasking support requires launch story board in bundle
- 【云计算】qcow2虚拟磁盘映像转化为vmdk
- shell 全局和局部变量
- [Lintcode]Plus One
- 设计模式(11)--Mediator中介者模式&Observer观察者模式
- UGUI点击事件(多个)
- SQL查询语句,怎样查询重复大于等于小于多少的数据
- 数据库_基础知识_GROUP BY 用法详解
- 视频插件VideoJS5介绍
- PowerShell 工作流简介
- 蓝桥杯历届-立方尾不变
- 用SpannableString和ImageSpan在textview中插入图片
- 高亮代码显示之HTML困惑
- WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 解决办法
- Css弹出菜单样式
- linux上安装apache以及httpd.conf基本配置