題意
給定一張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;
}