bzoj2007 [Noi2010]海拔

来源:互联网 发布:linux运维之道 pdf 编辑:程序博客网 时间:2024/05/17 03:20

题目链接:bzoj2007
题目大意:
一个规模为n的城市有(n+1)×(n+1)个交叉路口和2n×(n+1)条双向道路(简称道路),每条双向道路连接主干道上两个相邻的交叉路口。例如一张YT市的地图(n = 2),城市被划分为2×2个区域,包括3×3个交叉路口和12条双向道路。 小Z作为该市的市长,他根据统计信息得到了每天上班高峰期间YT市每条道路两个方向的人流量,即在高峰期间沿着该方向通过这条道路的人数。每一个交叉路口都有不同的海拔高度值,YT市市民认为爬坡是一件非常累的事情,每向上爬h的高度,就需要消耗h的体力。如果是下坡的话,则不需要耗费体力。因此如果一段道路的终点海拔减去起点海拔的值为h(注意h可能是负数),那么一个人经过这段路所消耗的体力是max{0, h}(这里max{a, b}表示取a, b两个值中的较大值)。 小Z还测量得到这个城市西北角的交叉路口海拔为0,东南角的交叉路口海拔为1(如上图所示),但其它交叉路口的海拔高度都无法得知。小Z想知道在最理想的情况下(即你可以任意假设其他路口的海拔高度),每天上班高峰期间所有人爬坡所消耗的总体力和的最小值。

注意,海拔是可以一样的,我以为一定要不同想了一下午!QwQ

题解:
求对偶图转最短路。
首先,可以知道海拔是可以一样的。那么我们就会想让一样的尽量多,于是左上角就会有一堆0,而右下角是一堆1,其实就是找个0-1的分界线。
就是直接在原图求最小割。【如果范围允许的话
可是对于100%的数据:1 ≤ n ≤ 500 就是有二十五万个点。
就要学对偶图这种东西了。。
图片转自http://blog.sina.com.cn/s/blog_86942b1401014ajk.html

要转对偶图的一般都是像这样的矩阵形式的吧。
学习资料:http://blog.sina.com.cn/s/blog_60707c0f01011fnn.html
设一个超级源点在附加面上,一个超级汇点在无界面。图中的每个面或者说每个区域中都有且只有一个点,原图中的边的割为对偶图的边,其流量就是边长。无向图就直接这样建就好了。
而有向图的话还要考虑方向。有一个好的方法就是把原图中的边全都顺时针或全都逆时针旋转90°,于是对偶图中的边的方向就是旋转后的边的方向。

神呐我搞了一个下午加半个晚上(加上打题解算大半个了QwQ)
为什么呢。
1. 看错题

  • 海拔能一样
  • 尽管输入竖边也是先从左到右再从上到下

2.边数组开小了!而bzoj提示我TLE啊。。于是我拿hyc的代码改啊改= =
对拍发现数组开小了还能WA啊orz

#include<cstdio>#include<cstdlib>#include<cstring>#include<queue>#include<iostream>#include<algorithm>using namespace std;#define maxn 300010struct node{    int x,y,c,next;}a[maxn*8];int len,first[maxn];void ins(int x,int y,int c){    len++;a[len].x=x;a[len].y=y;a[len].c=c;    a[len].next=first[x];first[x]=len;}struct nod{    int x,id;    bool operator < (const nod y) const    {        return x>y.x;    }};int S,T,d[maxn];priority_queue<nod> q;int dijkstra(){    memset(d,63,sizeof(d));    nod ls;ls.id=S;ls.x=0;    d[S]=0;q.push(ls);    while (!q.empty())    {        nod now=q.top();q.pop();        int x=now.id;        if (now.x!=d[x]) continue;        if (x==T) return d[x];        for (int k=first[x];k!=-1;k=a[k].next)        {            int y=a[k].y;            if (d[y]>d[x]+a[k].c)            {                d[y]=d[x]+a[k].c;                ls.id=y;ls.x=d[y];                q.push(ls);            }        }    }    return d[T];}int main(){    //freopen("a.in","r",stdin);    //freopen("a.out","w",stdout);    int n,i,j,x;    scanf("%d",&n);    S=n*n+1;T=S+1;len=0;    memset(first,-1,sizeof(first));    for (i=0;i<=n;i++)     for (j=1;j<=n;j++)     {         scanf("%d",&x);         if (i==0) ins(i*n+j,T,x);         else if (i==n) ins(S,(i-1)*n+j,x);         else ins(i*n+j,(i-1)*n+j,x);     }    for (i=1;i<=n;i++)     for (j=0;j<=n;j++)     {         scanf("%d",&x);         if (j==0) ins(S,(i-1)*n+1,x);         else if (j==n) ins(i*n,T,x);         else ins((i-1)*n+j,(i-1)*n+j+1,x);     }    for (i=0;i<=n;i++)     for (j=1;j<=n;j++)     {         scanf("%d",&x);         if (i==0) ins(T,i*n+j,x);         else if (i==n) ins((i-1)*n+j,S,x);         else ins((i-1)*n+j,i*n+j,x);     }    for (i=1;i<=n;i++)     for (j=0;j<=n;j++)     {         scanf("%d",&x);         if (j==0) ins((i-1)*n+1,S,x);         else if (j==n) ins(T,i*n,x);         else ins((i-1)*n+j+1,(i-1)*n+j,x);     }    printf("%d\n",dijkstra());    return 0;}
0 0
原创粉丝点击