[P4001 [ICPC-Beijing 2006]狼抓兔子]

P4001 [ICPC-Beijing 2006]狼抓兔子

题解:

这个题目已经给你建好图了,一看就是一个最小割,但是如果真的用最小割来写,肯定会 (TLE) ,看了题解发现这个是一个 网络流最小割平面图转对偶图求最短路

题解推荐博客:https://www.cnblogs.com/lher/p/7856451.html

看完题解之后,就可以自己开始写了。

注意这个每一个区域的点,是怎么定义的,因为一个格子有两个区域(也就是两个点),所以每一个格子的位置是 ((i,j)) 可以转化为数字 ((i-1)*(m-1)+j) ,因为每一个格子分成左右两个,所以继续转化,(x=((i-1)*(m-1)+j)*2) ,这样左边这个就等于 (x-1) ,右边这个区域就是 (x) ,最后就直接建图,跑最短路就可以了。

交的时候如果用 (vector) 建图,注意开 (O2) 优化。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
#define debug(x) printf("debug:%s=%d
",#x,x);
//#define debug(x) cout << #x << ": " << x << endl;
using namespace std;
typedef long long ll;
const int maxn = 1e3+5;
inline int read(){
    int X=0; bool flag=1; char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
    while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
    if(flag) return X;
    return ~(X-1);
}


int row[maxn][maxn],col[maxn][maxn],a[maxn][maxn],t,n,m;
struct node{
    int u,v,w;
    node(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
struct heapnode{
    int d,u;
    heapnode(int d,int u) : d(d),u(u) {}
    bool operator<(const heapnode &a) const{
        return a.d<d;
    }
};
vector<node>e[2*maxn*maxn];
void add(int u,int v,int w){
//    printf("u=%d v=%d w=%d
",u,v,w);
    if(u<0||v<0) return ;
    if(u>2*(n-1)*(m-1)+1||v>2*(n-1)*(m-1)+1) return;
    e[u].push_back(node(u,v,w));
    e[v].push_back(node(v,u,w));
}
ll d[2*maxn*maxn];
bool vis[2*maxn*maxn];
priority_queue<heapnode>que;
void dij(int s){
    while(!que.empty()) que.pop();
    for(int i=0;i<=t+10;i++) d[i]=inf64;
    d[s]=0;
    que.push(heapnode(0,s));
    while(!que.empty()){
        heapnode x=que.top();que.pop();
        int u=x.u;
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=0;i<e[u].size();i++){
            node now=e[u][i];
            if(d[now.v]>d[u]+now.w){
                d[now.v]=d[u]+now.w;
                que.push(heapnode(d[now.v],now.v));
            }
        }
    }
}


int main(){
//    scanf("%d%d",&n,&m);
    n = read(),m = read();
    int s=0;
    t=2*(n-1)*(m-1)+1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<m;j++) {
            row[i][j]=read();
//            scanf("%d",&row[i][j]);
        }
    for(int i=1;i<n;i++) {
        for(int j=1;j<=m;j++) {
            col[i][j]=read();
//            scanf("%d",&col[i][j]);
        }
    }
    for(int i=1;i<n;i++) {
        for(int j=1;j<m;j++) {
            a[i][j]=read();
//            scanf("%d",&a[i][j]);
        }
    }
    if(n==1){
        int ans = inf;
        for(int j=1;j<m;j++) ans=min(ans,row[1][j]);
        printf("%d
",ans);
        return 0;
    }
    if(m==1){
        int ans = inf;
        for(int i=1;i<n;i++) ans=min(ans,col[i][1]);
        printf("%d
",ans);
        return 0;
    }
    for(int i=1;i<n;i++){
        for(int j=1;j<m;j++){
            int u = ((i-1)*(m-1)+j)*2,v = u - 1;
            if(u>0&&u<=2*(n-1)*(m-1))  add(u,v,a[i][j]);
            int x = ((i-1)*(m-1)+j+1)*2-1;
            if(x>0&&x<=2*i*(m-1)&&u>0&&u<=2*(n-1)*(m-1))  add(u,x,col[i][j+1]);
            int y = (i*(m-1)+j)*2;
            if(y>0&&y<=2*(n-1)*(m-1))  add(v,y,row[i+1][j]);
//            printf("i=%d j=%d u=%d v=%d x=%d y=%d
",i,j,u,v,x,y);
        }
    }
    for(int i=1;i<n;i++){
        int u = ((i-1)*(m-1)+1)*2-1,v = i*(m-1)*2;
        if(u<0||v<0) continue;
        if(u<=2*(n-1)*(m-1))  add(s,u,col[i][1]);
        if(v<=2*(n-1)*(m-1))  add(t,v,col[i][m]);
    }
//    printf("
");
    for(int j=1;j<m;j++){
        int u = ((n-2)*(m-1)+j)*2-1,v=j*2;
        if(u<0||v<0) continue;
        if(u<=2*(n-1)*(m-1))  add(s,u,row[n][j]);
        if(v<=2*(n-1)*(m-1))  add(t,v,row[1][j]);
//        printf("u=%d v=%d col=%d row=%d
",u,v,row[n-1][j],row[1][j]);
    }
    dij(s);
    printf("%lld
",d[t]);
    return 0;
}


原文地址:https://www.cnblogs.com/EchoZQN/p/13322359.html