BZOJ1001

来源:互联网 发布:常州青蓝软件 编辑:程序博客网 时间:2024/05/19 19:30

开坑!

1001: [BeiJing2006]狼抓兔子

思路:平面图最小割
Orz周冬,主要思想都在他的文章《浅析最大最小定理在信息学竞赛中的应用》中提到

显然最大流不现实
将整个图从斜线切开,分为两块
若我们将每一块区域看成一个点,两块区域的公共边作为这两点的连边
显然,从左下到右上的最短路就是整个图的最小割
真是神思想!

代码:
我这个人比较喜欢手写优先队列……

#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <iostream>#include <algorithm>#define debug(...) fprintf(stderr,__VA_ARGS__)#define rint register int#define ull unsigned long longusing namespace std;const int MAXN=2*1000*1000+10,MAXM=6*1000*1000+10;int n,m;int s,t;#define heng(a,b) ((a-1)*2-(1-b))*(m-1)#define inf 1<<30int frontx[MAXM],fronty[MAXM],frontk[MAXM];int stdx[MAXN],orderx[MAXM];int nn,mm;void add(int x,int y,int k){    if (x!=t) { frontx[++mm]=x; fronty[mm]=y; frontk[mm]=k; }    if (y!=s) { frontx[++mm]=y; fronty[mm]=x; frontk[mm]=k; }    return ;}int num[MAXN];void Read(int &k){    char c=getchar(); k=0;    while (c<'0' || c>'9') c=getchar();    while (c>='0' && c<='9') {        k=k*10+c-'0';        c=getchar(); }    return ;}void sortx(){    for (rint i=1;i<=mm;i++)        num[frontx[i]]++;    for (rint i=1;i<=nn;i++) {        num[i]+=num[i-1];        stdx[i]=num[i]; }    for (rint i=1;i<=mm;i++)        orderx[++num[frontx[i]-1]]=i;    return ;}struct Heap{    unsigned int dis;    int x;}heap[MAXN];bool operator < (Heap A,Heap B) { return A.dis<B.dis; }int point[MAXN];void adjustup(int x){    static bool next;    next=true;    while (next) {        next=false;        static int f;        f=x/2;        if (f)            if (heap[x]<heap[f]) {                swap(heap[x],heap[f]);                point[heap[x].x]=x; point[heap[f].x]=f;                x=f; next=true; }}    return ;}void change(int l,int r){    swap(heap[l],heap[r]);    point[heap[r].x]=r; point[heap[l].x]=l;    return ;}void adjustdown(int x){    static bool next;    next=true;    while (next) {        next=false;         static int l,r;        l=x*2,r=x*2+1;        if (l<=nn)            if (r<=nn) {                if (heap[l]<heap[r] && heap[l]<heap[x]) {                    change(l,x);                    x=l; next=true; }                else if (heap[r]<heap[x]) {                    change(r,x);                    x=r; next=true; }            else if (heap[l]<heap[x]) {                change(l,x);                x=l; next=true; }}}    return ;}void dijsktra(){    for (rint i=1;i<=nn;i++) {        heap[i].dis=inf;        point[i]=heap[i].x=i; }    heap[s].dis=0;    adjustup(s);    while (nn) {        static Heap now;        now=heap[1];        if (now.x==t) {            cout<<heap[point[t]].dis<<endl;            return ; }        change(1,nn);        nn--; adjustdown(1);        static int x;        x=now.x;        for (rint i=stdx[x-1]+1;i<=stdx[x];i++) {            static int next;            next=fronty[orderx[i]];            if (heap[point[next]].dis>now.dis+frontk[orderx[i]]) {                heap[point[next]].dis=now.dis+frontk[orderx[i]];                adjustup(point[next]); }}}    return ;}void init(){    Read(n); Read(m);    if (n==1 || m==1) {        int nn=n,ans=inf;        if (nn==1) nn=m;        for (int k,i=1;i<nn;i++) {            Read(k);            ans=min(ans,k); }        if (ans==inf)            cout<<0<<endl;        else            cout<<ans<<endl;        return ; }    s=(n-1)*(m-1)*2+1,t=(n-1)*(m-1)*2+2;    nn=t;    for (rint i=1;i<=n;i++)        for (rint k,j=1;j<m;j++) {            Read(k);            if (i==1) add(s,heng(i,1)+j,k);            else if (i==n) add(heng(i,0)+j,t,k);            else add(heng(i,0)+j,heng(i,1)+j,k); }    for (rint i=1;i<n;i++)        for (rint k,j=1;j<=m;j++) {            Read(k);            if (j==1) add(t,heng(i+1,0)+j,k);            else if (j==m) add(s,heng(i,1)+j-1,k);            else add(heng(i,1)+j-1,heng(i+1,0)+j,k); }    for (rint i=1;i<n;i++)        for (rint k,j=1;j<m;j++) {            Read(k);            add(heng(i,1)+j,heng(i+1,0)+j,k); }    sortx();    dijsktra();    return ;}int main(){    init();    return 0;}
0 0
原创粉丝点击