链接
http://acm.hdu.edu.cn/showproblem.php?pid=6126
题解
网络流套路题(然而套路我早都忘光了)
点
(
i
,
j
)
(i,j)
(i,j)表示第
i
i
i个人收到的糖果数量
≥
j
\geq j
≥j
S
S
S连边到
(
i
,
1
)
(i,1)
(i,1),容量
∞
\infin
∞,
(
i
,
j
)
(i,j)
(i,j)连到
(
i
,
j
+
1
)
(
j
<
m
)
(i,j+1)(j<m)
(i,j+1)(j<m),容量
1000
−
w
i
j
1000-w_{ij}
1000−wij,然后
(
i
,
m
)
(i,m)
(i,m)连到
T
T
T,容量
1000
−
w
i
m
1000-w_{im}
1000−wim
这张图的最小割就就对应没有任何限制的时候的(
1000
n
−
1000n-
1000n−答案),但是有限制
x
−
y
≤
z
x-y\leq z
x−y≤z,
y
≥
x
−
z
y\geq x-z
y≥x−z
那么对于点
(
x
,
j
)
(x,j)
(x,j),向
(
y
,
j
−
z
)
(y,j-z)
(y,j−z)连
∞
\infin
∞的边,如果
j
−
z
>
m
j-z>m
j−z>m,那就向
T
T
T连
∞
\infin
∞的边
代码
#include <bits/stdc++.h>
#define maxn 3000
#define maxe 100000
#define iinf 0x3f3f3f3f
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
int read(int x=0)
{
int c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
struct Graph2
{
int head[maxn], next[maxe], to[maxe], w[maxe], c[maxe], tot;
void clear(int N)
{
int i;
for(i=1;i<=N;i++)head[i]=0;
for(i=2;i<=tot;i++)next[i]=0;
tot=1;
}
void add(int a, int b, int ww, int cc){to[++tot]=b;next[tot]=head[a];w[tot]=ww;c[tot]=cc;head[a]=tot;}
void adde(int a, int b, int ww,int cc){add(a,b,ww,cc);add(b,a,-ww,0);}
}G;
struct ISAP
{
int S, T, last[maxn], d[maxn], num[maxn], Exit;
void init(int N)
{
for(int i=1;i<=N;i++)d[i]=num[i]=0;
num[0]=N;
Exit=0;
}
int dfs(Graph2& G, int pos, int in)
{
int flow=0, t;
if(pos==T)return in;
for(int &p=last[pos];p;p=G.next[p])
if(G.c[p] and d[G.to[p]]+1==d[pos])
{
flow+= t=dfs(G,G.to[p],min(in-flow,G.c[p]));
G.c[p]-=t, G.c[p^1]+=t;
if(Exit or in==flow)return flow;
}
Exit=--num[d[pos]]==0;
++num[++d[pos]];
last[pos]=G.head[pos];
return flow;
}
int maxflow(Graph2& G)
{
int ans(0);
while(!Exit)
{
auto f=dfs(G,S,iinf);
if(f>10000)return -1;
ans+=f;
}
return ans;
}
}isap;
int N, M, K;
int main()
{
int T(read()), i, j, ok;
while(T--)
{
N=read(), M=read(), K=read();
G.clear(N*M+10);
isap.init(N*M+10);
isap.S=N*M+9, isap.T=N*M+10;
for(i=1;i<=N;i++)
{
for(j=1;j<=M;j++)
{
auto id=(i-1)*M+j;
if(j<M)G.adde(id,id+1,0,1000-read());
else G.adde(id,isap.T,0,1000-read());
if(j==1)G.adde(isap.S,id,0,iinf);
}
}
while(K--)
{
auto x=read(), y=read(), z=read();
// x-y <= z
// y >= x-z
for(i=1;i<=M;i++)
{
auto a=(x-1)*M+i, b=(y-1)*M+i-z;
if(1<=i-z and i-z<=M)G.adde(a,b,0,iinf);
if(i-z>M)G.adde(a,isap.T,0,iinf);
}
}
auto f=isap.maxflow(G);
if(f==-1)cout<<-1<<endl;
else cout<<-f+1000*N<<endl;
}
return 0;
}