您的位置:首页 > 其它

BZOJ1001

2015-06-11 18:13 411 查看
开坑!

1001: [BeiJing2006]狼抓兔子

思路:平面图最小割

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

显然最大流不现实

将整个图从斜线切开,分为两块

若我们将每一块区域看成一个点,两块区域的公共边作为这两点的连边

显然,从左下到右上的最短路就是整个图的最小割

真是神思想!

代码:

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

[code]#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 long
using 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<<30
int 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: