房间是个 n∗m 的网格,一共有 k 个窗户,都在上下左右四条边上。在第 0 时刻,每个窗户对应的格子上都会出现若干只蚊子。
蚊子每个时刻可以往上下左右移动一格或者呆在原地不动。
假设这些蚊子都足够聪明,请问最少花费多少时刻,使得所有格子上都有至少一只蚊子?
蚊子在第 0 时刻不能动。
1 ≤ m , n ≤ 1000 , 1 ≤ k ≤ 6 , 1 ≤ T ≤ 10 1\leq m,n \leq 1000 ,1\leq k \leq 6,1\leq T \leq 10 1≤m,n≤1000,1≤k≤6,1≤T≤10
二分时刻,蚊子可以从窗户那到处走,所以可以流向时刻内就能到达的点
因为有100w个点,肉眼可知会TLE,我们想想优化
发现有一些点与窗户连边的情况是相同的,所以就可以合成一个点,流的流量是这些点的个数和
这样就可以AC了
#include
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
#define PB push_back
#define CL clear
//#define int long long
#define fi first
#define se second
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
typedef pair<int,int> pii;
const int N = 100010;
const int inf = 1e9;
const int mod = 1e9+7;
inline int rd() {
char ch = getchar(); int p = 0; int f = 1;
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
struct node{int x,y,c,nex,other;}edge[N]; int len , fir[N]; int s,d;
void ins(int x,int y,int c) {
len++; int k1=len; edge[len].x=x; edge[len].y=y; edge[len].c=c; edge[len].nex=fir[x]; fir[x]=len;
len++; int k2=len; edge[len].x=y; edge[len].y=x; edge[len].c=0; edge[len].nex=fir[y]; fir[y]=len;
edge[k1].other=k2; edge[k2].other=k1;
}
struct Dinic{
int dep[N]; queue<int> q;
bool bfs() {
for(int i=s;i<=d;++i) dep[i] = 0;
while(!q.empty()) q.pop(); q.push(s); dep[s] = 1;
while(!q.empty()) {
int x = q.front();
for(int k=fir[x];k!=-1;k=edge[k].nex) {
int y = edge[k].y;
if(!dep[y] && edge[k].c) {
dep[y] = dep[x] + 1; q.push(y);
}
}q.pop();
}
return dep[d] > 0;
}
int dfs(int x,int flow) {
int delta = 0;
if(x==d) return flow;
for(int k=fir[x];k!=-1;k=edge[k].nex) {
int y=edge[k].y;
if(edge[k].c && flow > delta && dep[y] == dep[x]+1) {
int minf = dfs(y,min(edge[k].c , flow-delta));
edge[k].c-=minf; edge[edge[k].other].c+=minf;
delta+=minf;
}
}if(delta == 0) dep[x] = 0;
return delta;
}
}dinic;
int n,m,k;
tuple<int,int,int>tp[N];
int cnt[N];
void build(int length) {
s = 0; d =(1<<k)+k+1;
for(int i=s;i<=d;i++) fir[i] = -1; len = 0;
for(int i=0;i<(1<<k);i++) cnt[i] = 0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
int psta = 0;
for(int p=1;p<=k;p++)
if(abs(i-get<0>(tp[p])) + abs(j-get<1>(tp[p])) <= length)
psta |= (1<<(p-1));
// printf("%d %d %d\n",i,j,psta);
cnt[psta] ++;
}
for(int p=0;p<(1<<k);p++) ins(s,p+1,cnt[p]);
for(int p=0;p<(1<<k);p++) for(int q=1;q<=k;q++) if(p&(1<<(q-1)))
ins(p+1,(1<<k)+q,inf);
for(int p=1;p<=k;p++) ins((1<<k)+p,d,get<2>(tp[p]));
}
int check() {
int ans = 0;
while(dinic.bfs())
ans+=dinic.dfs(s,inf);
return ans == n*m;
}
signed main() {
int t = rd();
while(t--) {
n = rd(); m = rd(); k = rd();
rep(i,1,k) {
int x = rd(); int y = rd(); int d = rd();
tp[i] = make_tuple(x,y,d);
}
int l = 0; int r = n*m; int ret = -1;
while(l<=r) {
int mid = (l+r)>>1;
build(mid);
if(check()) ret=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ret);
}
return 0;
}