中文题意
首先可以肯定,如果,肯定-1
否则的话一定可以跑满所有点。
既然一定可以跑满所有点,那么剩下的即为检验问题。
可以发现当前的t满足二分的单调性,如果最小的t可以,那么t+1一定也可以。
所以说就可以二分当前的时间t,看t是否存在一种合法的分配方案。
考虑到一个性质,一个蚊子只能占据一个,所以和网络流相关。
接下来就变成了,使用网络流检验当前t是否合法
如何建图呢?
我们可以这么想:首先S点对k个窗户的流量为a[k],之后每个窗户可以对当前t时间内可到达的点都有1的流量,之后每个点向汇点S都有1的流量,之后只需要检验最大流是否为n*m即可
但是这样建图的话 任何一种最大流的算法也没有合理的复杂度去处理这个问题,所以考虑一下建图。
如何优化建图呢?
考虑其实某些点是可以合并的,第k个窗户在t时间内可以到达的点集就完全可以合并,流量为a[k](设为当前最大值即可)。
之后状态压缩一下,假设x第k位为1,表示第k个窗户可以到达该点(状态),也就是说这个状态里的所有点第k个窗户都可以到达,所以此时只需要从k个窗户 向 x状态输送 点集大小的流量即可。
这样就完成了缩点,把k个窗户以及所有状态看为点,建图之后,跑一下最大流即可。
/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#include
#define debug(x) cout<<#x<<":"< pp;
const ll INF=1e17;
const int Maxn=2e7+10;
const int maxn =2e3+10;
const int mod=998244353;
const int Mod = 1e9+7;
///const double eps=1e-10;
inline bool read(ll &num)
{char in;bool IsN=false;
in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p,S,T;
///Net Flow
ll cnt = 2;
int head[maxn],cur[maxn],gap[maxn],d[maxn];///当前弧优化 、 断层
ll flow[maxn];
int MAX;
struct node{
int e,next;
ll w;
}edge[maxn];
void _inint_(){
memset(head,0,sizeof(head));
memchr(cur,0,sizeof(cur));
memset(gap,0,sizeof(gap));
cnt = 2;
}
void addedge(int u,int v,ll w){
edge[cnt] = node{v,head[u],w};
head[u] = cnt++;
}
void bfs(){
memset(d,0,sizeof(d));
queueq;q.push(T);d[T] = 1;
while(!q.empty()){
int u = q.front();q.pop();
for(int i=head[u];i;i=edge[i].next){
int e = edge[i].e;
if(d[e]) continue;
d[e] = d[u]+1;
++gap[d[e]];
q.push(e);
}
}
for(int i=0;i<=MAX+p+2;i++) cur[i] = head[i];///now
}
ll dfs(int u,ll flow){///
if(u == T) return flow;
ll delta = 0,temp;
for(int i=cur[u];i;i=edge[i].next){
int e = edge[i].e;
if(d[u] != d[e]+1||edge[i].w<=0) continue;
temp = dfs(e,min(flow-delta,edge[i].w));
if(temp<=0) continue;
edge[i].w -= temp;
edge[i^1].w += temp;
delta += temp;
if(delta == flow) return flow;
}
///否则出现断层
if(--gap[d[u]]==0) d[S] = T+1;
++gap[++d[u]];
cur[u] = head[u];
return delta;
}
ll ISAP(){
ll maxflow = 0,delta = 0;
bfs();
while(d[S] <= T) maxflow += dfs(S,INF);
return maxflow;
}
///Net Flow
struct Point{
int x,y,a;
}q[15];;
int ct[120];
int judge(int x){
memset(ct,0,sizeof(ct));
for(int i=1;i<=n;i++){
for(int k=1;k<=m;k++){
ll temp = 0;
for(int j=1;j<=p;j++){
int dis = abs(q[j].x-i)+abs(q[j].y-k);
if(dis<=x) temp ^= 1<<(j-1);
}
ct[temp]++;
}
}///预处理tp[i][k] 缩点
_inint_();
S = MAX+p,T = S+1;
for(int i=0;i>pk&1){
addedge(MAX+pk,i,q[k].a);
addedge(i,MAX+pk,0);
}
}
}
for(int i=0;i