【BZOJ1001】狼抓兔子(BJOI2006)-平面图最小割转最短路

来源:互联网 发布:js实现html业务流程图 编辑:程序博客网 时间:2024/06/04 17:57

测试地址:狼抓兔子
做法:本题需要用到平面图最小割转最短路。
注意到题目中要求一个平面图的最小割,然而这个图点数太多,我们不可能直接用网络流求解,但是我们注意到,如果在平面图中每两个相邻区域之间连双向边(我们把右、上边界和左、下边界看做两个不相邻的平面区域),边的长度为这两个区域的公共边的权值,这时候我们发现,每一个割都对应了一条从右、上边界到左、下边界的路径,因此按这样建图之后跑最短路即可,因为SPFA会被卡,因此用Dijkstra实现即可,时间复杂度为O(nmlog(nm))。注意特判n=1m=1的情况。
以下是本人代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <queue>#define inf 1000000000using namespace std;int n,m,x,first[2000010]={0},tot=0,t,dis[2000010];struct edge {int v,d,next;} e[12000010];bool vis[2000010]={0};struct point{    int val,id;    bool operator < (point a) const    {        return val>a.val;    }};priority_queue <point> Q;void insert(int a,int b,int d){    e[++tot].v=b;    e[tot].d=d;    e[tot].next=first[a];    first[a]=tot;}void dijkstra(){    point now,nxt;    now.val=0,now.id=0;    vis[0]=1,dis[0]=0;    for(int i=1;i<=t;i++) dis[i]=inf;    for(int i=first[0];i;i=e[i].next)    {        nxt.val=e[i].d;        nxt.id=e[i].v;        dis[e[i].v]=e[i].d;        Q.push(nxt);    }    while(!Q.empty())    {        now=Q.top();        while(vis[now.id]&&!Q.empty()) Q.pop(),now=Q.top();        if (Q.empty()) break;        vis[now.id]=1;        for(int i=first[now.id];i;i=e[i].next)            if (dis[e[i].v]>dis[now.id]+e[i].d)            {                dis[e[i].v]=dis[now.id]+e[i].d;                nxt.id=e[i].v;                nxt.val=dis[e[i].v];                Q.push(nxt);            }    }}int main(){    scanf("%d%d",&n,&m);    t=2*(n-1)*(m-1)+1;    int minx=inf;    for(int i=1;i<m;i++)    {        scanf("%d",&x);        minx=min(x,minx);        insert(0,i,x);    }    for(int i=1;i<n-1;i++)    {        int s=(2*i-1)*(m-1);        for(int j=1;j<m;j++)        {            scanf("%d",&x);            minx=min(minx,x);            insert(s+j,s+j+m-1,x);            insert(s+j+m-1,s+j,x);        }    }    for(int i=1;i<m;i++)    {        scanf("%d",&x);        minx=min(minx,x);        insert((2*n-3)*(m-1)+i,t,x);    }    for(int i=1;i<n;i++)    {        int s=(2*i-1)*(m-1);        scanf("%d",&x);        minx=min(minx,x);        insert(s+1,t,x);        for(int j=2;j<m;j++)        {            scanf("%d",&x);            minx=min(minx,x);            insert(s+j,s+j-m,x);            insert(s+j-m,s+j,x);        }        scanf("%d",&x);        minx=min(minx,x);        insert(0,s,x);    }    for(int i=1;i<n;i++)    {        int s=(2*i-1)*(m-1);        for(int j=1;j<m;j++)        {            scanf("%d",&x);            minx=min(minx,x);            insert(s+j,s+j-m+1,x);            insert(s+j-m+1,s+j,x);        }    }    if (n==1||m==1) {printf("%d",minx);return 0;}    dijkstra();    printf("%d",dis[t]);    return 0;}
阅读全文
0 0