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;
}

posted @ 2018-02-22 23:32  zhou888  阅读(177)  评论(0编辑  收藏  举报