gym 101194 J Mr.Panda and TubeMaster (費用流)

題意

給定一張n*m的方格,每個方格放可以放4種類型的直角管道,並給出幾個重要點,保證每個重要點都存在管道,且管道圍成一個環。現給出每個管道連接兩個方格能賺的錢,輸出最多賺多少錢。若不存在方案輸出impossible。

題解

可以發現每個方格都存在上下流向和左右流向的管道,且方格之間相互連接的管道方向是不同的,因此想到可以將方格黑白染色,白色代表該方格中的管道只左右流,黑色代表該方格中的管道只上下流,之後我們再把點拆成出點和入點,就可以將相鄰方格連接起來了,之後我們設定流量上線爲n*m,即每個方格都存在流量,對於那些非重要點,我們將其出點連向入點,代表該方格無管道,之後跑個最大費用最大流即可

代碼

/**
 *     author:     TelmaZzzz
 *     create:     2019-10-06-17.59.54
**/
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
//#include <random>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(db &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
void _W(const int &x) { printf("%d", x); }
void _W(const ll &x) { printf("%lld", x); }
void _W(const db &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template<class T> void _W(const vector<T> &x) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() {}
template<class T, class... U> void W(const T &head, const U &... tail) { _W(head); putchar(sizeof...(tail) ? ' ' : '\n'); W(tail...); }
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define erp(x,y,z) for(int x=y;x>=z;x--)
#define PB push_back
#define MP make_pair
#define INF 1073741824
#define inf 1152921504606846976
#define pi 3.14159265358979323846
#define Fi first
#define Se second
//#pragma comment(linker,"/STACK:10240000,10240000")
//mt19937 rand_(time(0));
const int N=3000,M=10000;
const long long mod=1e9+7;
inline int read(){int ret=0;char ch=getchar();bool f=1;for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');for(;isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;return f?ret:-ret;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}//逆元
int cost[M],wei[M];
int head[N],NEXT[M],ver[M],tot;void link(int u,int v,int w,int val){ver[++tot]=v;NEXT[tot]=head[u];head[u]=tot;wei[tot]=w;cost[tot]=val;
}
void TelmaZzzz(){
#ifndef ONLINE_JUDGE
    freopen("1.txt","r",stdin);
#endif
}

int n,m;
int S,T;
int maxflow;
int ans;
int row[50][50],col[50][50];
bool mark[50][50];
int change(int x,int y){
    return (x-1)*m+y;
}
void init(){
    rep(i,S,T) head[i]=0;
    tot=1;
    maxflow=ans=0;
    memset(mark,false,sizeof(mark));
}
int d[N],incf[N],pre[N];
bool vis[N];
bool spfa(){
    queue<int>q;
    rep(i,S,T) d[i]=-INF,vis[i]=false;
    q.push(S);
    d[S]=0;
    vis[S]=true;
    incf[S]=INF;
    while(q.size()){
        int x=q.front();
        vis[x]=false;
        q.pop();
        for(int i=head[x];i;i=NEXT[i]){
            int y=ver[i];
            if(!wei[i]) continue;
            if(d[y]<d[x]+cost[i]){
                d[y]=d[x]+cost[i];
                incf[y]=min(incf[x],wei[i]);
                pre[y]=i;
                if(!vis[y]) vis[y]=true,q.push(y);
            }
        }
    }
    if(d[T]==-INF) return false;
    return true;
}
void update(){
    int x=T;
    while(x!=S){
        int i=pre[x];
        wei[i]-=incf[T];
        wei[i^1]+=incf[T];
        x=ver[i^1];
    }
    maxflow+=incf[T];
    ans+=d[T]*incf[T];
}
int main(){
    TelmaZzzz();
    //ios::sync_with_stdio(false);
    int t;
    R(t);
    int ti=0;
    while(t--){
        R(n,m);
        S=1,T=n*m*2+3;
        init();
        rep(i,1,n){
            rep(j,1,m-1){
                R(row[i][j]);
            }
        }
        rep(i,1,n-1){
            rep(j,1,m){
                R(col[j][i]);
            }
        }
        int Q;
        R(Q);
        int u,v;
        rep(i,1,Q){
            R(u,v);
            mark[u][v]=true;
        }
        rep(i,1,n){
            rep(j,1,m){
                if((j+i)%2==0){
                    if(j>1){
                        link(change(i,j)+1,change(i,j-1)+n*m+1,1,row[i][j-1]);
                        link(change(i,j-1)+1+n*m,change(i,j)+1,0,-row[i][j-1]);
                    }
                    if(j<m){
                        link(change(i,j)+1,change(i,j+1)+n*m+1,1,row[i][j]);
                        link(change(i,j+1)+1+n*m,change(i,j)+1,0,-row[i][j]);
                    }
                }
                else {
                    if(i>1){
                        link(change(i,j)+1,change(i-1,j)+n*m+1,1,col[j][i-1]);
                        link(change(i-1,j)+1+n*m,change(i,j)+1,0,-col[j][i-1]);
                    }
                    if(i<n){
                        link(change(i,j)+1,change(i+1,j)+n*m+1,1,col[j][i]);
                        link(change(i+1,j)+1+n*m,change(i,j)+1,0,-col[j][i]);
                    }
                }
                link(S,change(i,j)+1,1,0);
                link(change(i,j)+1,S,0,0);
                link(change(i,j)+1+n*m,T,1,0);
                link(T,change(i,j)+1+n*m,0,0);
                if(mark[i][j]) continue;
                link(change(i,j)+1,change(i,j)+n*m+1,1,0);
                link(change(i,j)+n*m+1,change(i,j)+1,0,0);
            }
        }
        while(spfa()) update();
        printf("Case #%d: ",++ti);
        if(maxflow!=n*m) puts("Impossible");
        else {
            printf("%d\n",ans);
        }
    }
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章