[BZOJ2007]NOI2010海拔|最小割|平面图转对偶图|最短路
2015-04-23 14:35
465 查看
好久以前就想做但是那个时候不会做。。
题目说海拔不一定是整数,纯属坑爹嘛。。可以证明如果有小数定不是最优(能贪就多贪嘛)。。然后显然最优的时候一定是走到了1就不会回到0了,也就是要分成两个点集,一个0,一个1,这不就是一最小割嘛。。
看一看最大数据,250000+个点,直接跑最大流要挂。。注意到是平面图,而且S,T都在边界上,所以可以转对偶图跑最短路。。这里最要小心的就是rebuild的时候连边的问题,比如一条南北走向的边是(u,v)u在上,假设把新的S放在图的左下(意会一下),那么如果一条新边从东向西地穿过了(u,v),那么一定是将v留在了S集,u留在了T集,这个随便脑补一下就知道了,所以这时候这条新边的长度应该等于v到u的人数。。其他的都类似,脑补一下。。
题目说海拔不一定是整数,纯属坑爹嘛。。可以证明如果有小数定不是最优(能贪就多贪嘛)。。然后显然最优的时候一定是走到了1就不会回到0了,也就是要分成两个点集,一个0,一个1,这不就是一最小割嘛。。
看一看最大数据,250000+个点,直接跑最大流要挂。。注意到是平面图,而且S,T都在边界上,所以可以转对偶图跑最短路。。这里最要小心的就是rebuild的时候连边的问题,比如一条南北走向的边是(u,v)u在上,假设把新的S放在图的左下(意会一下),那么如果一条新边从东向西地穿过了(u,v),那么一定是将v留在了S集,u留在了T集,这个随便脑补一下就知道了,所以这时候这条新边的长度应该等于v到u的人数。。其他的都类似,脑补一下。。
#include<iostream> #include<cstdio> #define N 260005 #define inf 0x3f3f3f3f using namespace std; struct edge{ int e,q,next; }ed[N*4]; int n,q,i,j,s,t,x,ne=1,nd=0,a ,d ,heap ,u ; void add(int s,int e,int q) { ed[++ne].e=e;ed[ne].q=q; ed[ne].next=a[s];a[s]=ne; } void build() { //p1 for (i=1;i<=n;i++) scanf("%d",&q),add(s,i,q); for (i=1;i<n;i++) for (j=1;j<=n;j++) { scanf("%d",&q); x=i*n+j; add(x-n,x,q); } for (i=1;i<=n;i++) scanf("%d",&q),add((n-1)*n+i,t,q); //p2 for (i=1;i<=n;i++) { scanf("%d",&q); x=(i-1)*n+1; add(x,t,q); for (j=1;j<n;j++) { scanf("%d",&q); x=(i-1)*n+j; add(x+1,x,q); } scanf("%d",&q); x=i*n; add(s,x,q); } //p3 for (i=1;i<=n;i++) scanf("%d",&q); for (i=1;i<n;i++) for (j=1;j<=n;j++) { scanf("%d",&q); x=i*n+j; add(x,x-n,q); } for (i=1;i<=n;i++) scanf("%d",&q); //p4 for (i=1;i<=n;i++) { scanf("%d",&q); for (j=1;j<n;j++) { scanf("%d",&q); x=(i-1)*n+j; add(x,x+1,q); } scanf("%d",&q); } } void del() { u[heap[1]]=0; heap[1]=heap[nd--]; int i=1; while((i<<=1)<=nd) { if (i<nd&&d[heap[i+1]]<d[heap[i]]) i++; if (d[heap[i]]<d[heap[i>>1]]) swap(u[heap[i]],u[heap[i>>1]]),swap(heap[i],heap[i>>1]);else break; } } void up(int x) { while (x>1&&d[heap[x]]<d[heap[x>>1]]) swap(u[heap[x]],u[heap[x>>1]]),swap(heap[x],heap[x>>1]),x>>=1; } void ins(int x) { heap[++nd]=x;u[x]=nd;up(nd); } void dij(int s) { ins(s);d[s]=0; int x,j,to; for (int i=1;i<t;i++) { x=heap[1];del(); if (x==t) return; for (j=a[x];j;j=ed[j].next) if (d[x]+ed[j].q<d[to=ed[j].e]) { d[to]=d[x]+ed[j].q; if (u[to]) up(u[to]);else ins(to); } } } int main() { freopen("2007.in","r",stdin); scanf("%d",&n); s=n*n+1;t=n*n+2; for (i=1;i<=t;i++) a[i]=0,u[i]=0,d[i]=inf; build(); dij(s); printf("%d\n",d[t]); }
相关文章推荐
- 【BZOJ2007】【NOI2010】海拔(最小割,平面图转对偶图,最短路)
- 【BZOJ2007】【NOI2010】海拔(最小割,平面图转对偶图,最短路)
- [BZOJ 2007] [Noi2010] 海拔 【平面图最小割(对偶图最短路)】
- bzoj2007 [Noi2010]海拔(平面图最小割转对偶图最短路)
- BZOJ 2007 NOI 2010 海拔 平面图最小割->最短路SPFA+pq
- BZOJ.2007.[NOI2010]海拔(最小割 对偶图最短路)
- 【BZOJ2007】【Noi2010】海拔 平面图最小割转最短路
- [BZOJ2007][NOI2010]海拔(对偶图最短路)
- 【BZOJ2007】[Noi2010]海拔 对偶图最短路
- [BZOJ 2007][NOI 2010]海拔(平面图最小割)
- 【BZOJ-2007】海拔 最小割 (平面图转对偶图 + 最短路)
- BZOJ 2007 NOI2010 海拔 平面图最小割
- BZOJ2007 [Noi2010]海拔 【平面图最小割转对偶图最短路】
- 【平面图最小割】BZOJ2007-[NOI2010]海拔
- 【BZOJ 2007】 2007: [Noi2010]海拔 (平面图转对偶图+spfa)
- bzoj 2007: [Noi2010]海拔(最短路)
- 【bzoj2007】[Noi2010]海拔 最小割+对偶图+最短路
- B20J_2007_[Noi2010]海拔_平面图最小割转对偶图+堆优化Dij
- 平面圖最小割 BZOJ1001: [BeiJing2006]狼抓兔子 BZOJ 2007: [Noi2010]海拔
- BZOJ 2007 NOI2010 海拔高度 最小减产计划