您的位置:首页 > 其它

[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的人数。。其他的都类似,脑补一下。。
#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]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: