zoukankan      html  css  js  c++  java
  • bzoj1001狼抓兔子

    1001: [BeiJing2006]狼抓兔子

    现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
    而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
    左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路
    1:(x,y)< == >(x+1,y)
    2:(x,y)< == >(x,y+1)
    3:(x,y)< == >(x+1,y+1)
    道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
    开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
    这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
    才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
    狼的数量要最小。因为狼还要去找喜羊羊麻烦.

    对偶图的第一题。

    平面图的对偶图是把平面图的面变成点,外面的部分变为一个点。

    如果要求一个平面图的最大流,我们可以把它转化为它对偶图的最短路。

    #include<bits/stdc++.h>
    using namespace std;
    #define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
    #define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
    #define id(x,y) ((x-1)*m+y)
    typedef long long ll;
    inline int read(){
        int x;
        char c;
        int f=1;
        while((c=getchar())!='-' && (c<'0' || c>'9'));
        if(c=='-') c=getchar(),f=-1;
        x=c^'0';
        while((c=getchar())>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0');
        return x*f;
    }
    inline ll readll(){
        ll x;
        char c;
        ll f=1;
        while((c=getchar())!='-' && (c<'0' || c>'9'));
        if(c=='-') c=getchar(),f=-1;
        x=c^'0';
        while((c=getchar())>='0' && c<='9') x=(x<<1ll)+(x<<3ll)+(c^'0');
        return x*f;
    }
    const int maxn=2000000+10,inf=0x3f3f3f3f;
    int Begin[maxn],Next[maxn*3],to[maxn*3],w[maxn*3],e;
    inline bool chkmin(int &x,int y){return (y<x)?(x=y,1):0;}
    void add_edge(int x,int y,int z){
        to[++e]=y;
        Next[e]=Begin[x];
        Begin[x]=e;
        w[e]=z;
    }
    void add(int x,int y){
        int z=read();
        add_edge(x,y,z),add_edge(y,x,z);
    }
    struct point{
        int x,y;
        bool operator <(const point &rhs) const{
            return y>rhs.y;
        }
    };
    priority_queue<point> q;
    bool vis[maxn];
    int d[maxn];
    int S,T;
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("dot.in","r",stdin);
        freopen("dot.out","w",stdout);
    #endif
        int n=read(),m=read();
        if(n==1 || m==1){
            if(n>m) swap(n,m);
            int ans=inf;
            REP(i,1,m-1){
                int x=read();
                chkmin(ans,x);
            }
            if(ans==inf) printf("0\n");
            else printf("%d\n",ans);
            return 0;
        }
        n--,m--;
        S=n*m*2+1,T=n*m*2+2;
        REP(i,1,m) add(S,id(1,i)*2-1);
        REP(i,2,n) REP(j,1,m) add(id(i-1,j)*2,id(i,j)*2-1);
        REP(i,1,m) add(id(n,i)*2,T);
        REP(i,1,n)
            REP(j,1,m+1){
                if(j==1) add(id(i,j)*2,T);
                else if(j==jend) add(S,id(i,j-1)*2-1);
                else add(id(i,j)*2,id(i,j-1)*2-1);
            }
        REP(i,1,n) REP(j,1,m) add(id(i,j)*2-1,id(i,j)*2);
        memset(d,inf,sizeof(d));
        q.push((point){S,0});d[S]=0;
        while(!q.empty()){
            point u=q.top();q.pop();
            if(vis[u.x]) continue;
            vis[u.x]=1;
            if(u.x==T){
                printf("%d\n",u.y);
                return 0;
            }
            for(int i=Begin[u.x];i;i=Next[i])
                if(chkmin(d[to[i]],u.y+w[i]) && !vis[to[i]])
                    q.push((point){to[i],d[to[i]]});
        }
        return 0;
    }
    
    
  • 相关阅读:
    JS和C# 里的闭包及闭包在事件中的使用
    ***项目开发记录
    七牛云存储之应用视频上传系统开心得
    二维码及二维码接合短URL的应用
    EF批量添加,删除,修改的扩展
    ngTemplateOutlet递归的问题
    每日新知2019-06-03
    Spring boot初始
    纯前端播放本地音乐
    macbook 安装任意来源
  • 原文地址:https://www.cnblogs.com/zhou888/p/8460530.html
Copyright © 2011-2022 走看看