zoukankan      html  css  js  c++  java
  • BZOJ1001 BJOI2006狼抓兔子(最小割+最短路)

      显然答案就是最小割。直接跑dinic也能过,不过显得不太靠谱。

      考虑更正确的做法。作为一个平面图,如果要把他割成两半,那么显然可以用一条曲线覆盖且仅覆盖所有割边。于是我们把空白区域看成点,隔开他们的边看成边,原图的最小割就是这张新图中能割开原起点和终点的两个区域之间的最短路。

      建出来的新图就是原图的对偶图。平面图最小割=对偶图最短路。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 1010
    #define S 2000000
    #define T 2000001
    int n,m,d[N*N<<1],p[N*N<<1],t=0;
    struct data{int to,nxt,len;
    }edge[N*N*6];
    bool flag[N*N<<1];
    struct point
    {
        int x,d;
        bool operator <(const point&a) const
        {
            return d>a.d;
        }
    };
    priority_queue<point> q;
    int trans(int x,int y,int p)
    {
        if (x==0) return S;
        if (x==n) return T;
        if (y==0) return T;
        if (y==m) return S;
        return ((x-1)*(m-1)+(y-1)<<1)+p;
    }
    void addedge(int x,int y,int z)
    {
        t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;
        t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].len=z,p[y]=t;
    }
    void dijkstra()
    {
        q.push((point){S,0});
        memset(d,42,sizeof(d));d[S]=0;
        for (int i=1;i<=trans(n,m,1)+2;i++)
        {
            while (!q.empty()&&flag[q.top().x]) q.pop();
            if (q.empty()) break;
            point k=q.top();q.pop();
            flag[k.x]=1;
            for (int j=p[k.x];j;j=edge[j].nxt)
            if (k.d+edge[j].len<d[edge[j].to])
            {
                d[edge[j].to]=k.d+edge[j].len;
                q.push((point){edge[j].to,d[edge[j].to]});
            }
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj1001.in","r",stdin);
        freopen("bzoj1001.out","w",stdout);
        const char LL[]="%I64d";
    #else
        const char LL[]="%lld";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++)
            for (int j=1;j<m;j++)
            {
                int x=read();
                addedge(trans(i-1,j,1),trans(i,j,0),x);
            }
        for (int i=1;i<n;i++)
            for (int j=1;j<=m;j++)
            {
                int x=read();
                addedge(trans(i,j-1,0),trans(i,j,1),x);
            }
        for (int i=1;i<n;i++)
            for (int j=1;j<m;j++)
            {
                int x=read();
                addedge(trans(i,j,0),trans(i,j,1),x);
            }
        dijkstra();
        cout<<d[T];
        return 0;
    }
  • 相关阅读:
    SSH公/私秘钥的生成及使用
    使用docker-compose部署Kafka集群
    使用docker或者docker-compose部署Zookeeper集群
    zookeeper相关概念
    redis相关概念
    mq-rabbitmq
    mysql事务隔离级别
    新自动化测试框架+微信机器人构建思路
    当eclipse调用tomcat的时候发生了什么?
    .net 获取配置项
  • 原文地址:https://www.cnblogs.com/Gloid/p/9413782.html
Copyright © 2011-2022 走看看