题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6749
(占个坑,有空再更新题解)
Dinic:
#include
#include
#include
using namespace std;
struct forward_star
{
int next,to,w;
};
int t;
int n,m,k;
int x[7];
int y[7];
int z[7];
int a[72][72];
int f[64];
bool vis[72];
int head[72];
int dist[72];
int que[72];
forward_star edge[10369];
int cnt;
int abs(int x)
{
if (x < 0)
return (-x);
else return x;
}
bool bfs(int now)
{
memset(dist,0,sizeof(dist));
memset(vis,0,sizeof(vis));
vis[now] = true;
int f = 1;
int t = 1;
que[1] = now;
while (f <= t)
{
int now = que[f];
int i = head[now];
while (i)
{
if (edge[i].w && !vis[edge[i].to])
{
vis[edge[i].to] = true;
dist[edge[i].to] = dist[now] + 1;
que[++t] = edge[i].to;
}
i = edge[i].next;
}
f ++;
}
return dist[71];
}
int dfs(int now,int delta)
{
int tot = 0;
if (now == 71)
return delta;
int i = head[now];
while (i)
{
if (edge[i].w && dist[edge[i].to] == dist[now] + 1)
{
int temp = dfs(edge[i].to,min(delta - tot,edge[i].w));
if (temp)
{
tot += temp;
edge[i].w -= temp;
edge[i ^ 1].w += temp;
}
if (tot == delta)
return delta;
}
i = edge[i].next;
}
return tot;
}
void add(int u,int v,int w)
{
cnt ++;
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
cnt ++;
edge[cnt].to = u;
edge[cnt].w = 0;
edge[cnt].next = head[v];
head[v] = cnt;
}
bool check(int t)
{
cnt = 1;
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++)
{
int status = 0;
for (int p = 1;p <= k;p ++)
if (abs(i - x[p]) + abs(j - y[p]) <= t)
status ^= (1 << p - 1);
f[status] ++;
}
for (int i = 1;i <= k;i ++)
{
add(70,i + (1 << k) - 1,z[i]);
for (int j = 0;j < (1 << k);j ++)
if (j & (1 << i - 1))
add(i + (1 << k) - 1,j,z[i]);
}
for (int i = 0;i < (1 << k);i ++)
add(i,71,f[i]);
int ans = 0;
while (bfs(70))
ans += dfs(70,2147483647);
if (ans != n * m)
return false;
else return true;
}
int main()
{
scanf("%d",&t);
while (t --)
{
memset(f,0,sizeof(f));
scanf("%d%d%d",&n,&m,&k);
int sum = 0;
for (int i = 1;i <= k;i ++)
{
scanf("%d%d%d",&x[i],&y[i],&z[i]);
sum += z[i];
}
if (sum < n * m)
{
printf("-1\n");
continue;
}
int l = 0;
int r = n + m;
while (l < r - 1)
{
int mid = l + r + 1 >> 1;
if (check(mid))
r = mid;
else l = mid + 1;
}
if (check(l))
printf("%d\n",l);
else printf("%d\n",r);
}
return 0;
}
FF:
#include
#include
#include
using namespace std;
struct forward_star
{
int next,to,w;
};
int t;
int n,m,k;
int f[64];
int x[7];
int y[7];
int z[7];
int a[72][72];
bool vis[72];
int head[72];
forward_star edge[10369];
int cnt;
int abs(int x)
{
if (x < 0)
return (-x);
else return x;
}
int dfs(int now,int delta)
{
vis[now] = true;
int tot = 0;
if (now == 71)
{
vis[now] = false;
return delta;
}
int i = head[now];
while (i)
{
if (edge[i].w && !vis[edge[i].to])
{
int temp = dfs(edge[i].to,min(delta - tot,edge[i].w));
if (temp)
{
tot += temp;
edge[i].w -= temp;
edge[i ^ 1].w += temp;
}
if (tot == delta)
{
vis[now] = false;
return delta;
}
}
i = edge[i].next;
}
vis[now] = false;
return tot;
}
void add(int u,int v,int w)
{
cnt ++;
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
cnt ++;
edge[cnt].to = u;
edge[cnt].w = 0;
edge[cnt].next = head[v];
head[v] = cnt;
}
bool check(int t)
{
memset(f,0,sizeof(f));
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++)
{
int status = 0;
for (int p = 1;p <= k;p ++)
if (abs(i - x[p]) + abs(j - y[p]) <= t)
status ^= (1 << p - 1);
f[status] ++;
}
cnt = 1;
memset(head,0,sizeof(head));
for (int i = 1;i <= k;i ++)
{
add(70,i + (1 << k) - 1,z[i]);
for (int j = 0;j < (1 << k);j ++)
if (j & (1 << i - 1))
add(i + (1 << k) - 1,j,z[i]);
}
for (int i = 0;i < (1 << k);i ++)
add(i,71,f[i]);
int ans = 0;
bool flag = false;
while (!flag)
{
flag = true;
int delta = dfs(70,2147483647);
if (delta)
{
ans += delta;
flag = false;
}
}
if (ans != n * m)
return false;
else return true;
}
int main()
{
scanf("%d",&t);
while (t --)
{
memset(f,0,sizeof(f));
scanf("%d%d%d",&n,&m,&k);
int sum = 0;
for (int i = 1;i <= k;i ++)
{
scanf("%d%d%d",&x[i],&y[i],&z[i]);
sum += z[i];
}
if (sum < n * m)
{
printf("-1\n");
continue;
}
int l = 0;
int r = n + m;
while (l < r - 1)
{
int mid = l + r + 1 >> 1;
if (check(mid))
r = mid;
else l = mid + 1;
}
if (check(l))
printf("%d\n",l);
else printf("%d\n",r);
}
return 0;
}
EK:
#include
#include
#include
using namespace std;
int t;
int n,m,k;
int f[64];
int x[7];
int y[7];
int z[7];
int a[72][72];
int pre[72];
bool vis[72];
int abs(int x)
{
if (x < 0)
return (-x);
else return x;
}
int dfs(int now,int delta)
{
vis[now] = true;
if (now == 71)
{
vis[now] = false;
return delta;
}
for (int i = 0;i < 72;i ++)
if (a[now][i] && !vis[i])
{
pre[i] = now;
int temp = dfs(i,min(delta,a[now][i]));
if (temp)
{
vis[now] = false;
return temp;
}
pre[i] = 0;
}
vis[now] = false;
return 0;
}
bool check(int t)
{
memset(f,0,sizeof(f));
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++)
{
int status = 0;
for (int p = 1;p <= k;p ++)
if (abs(i - x[p]) + abs(j - y[p]) <= t)
status ^= (1 << p - 1);
f[status] ++;
}
memset(a,0,sizeof(a));
for (int i = 1;i <= k;i ++)
{
a[70][i + (1 << k) - 1] = z[i];
a[i + (1 << k) - 1][70] = 0;
for (int j = 0;j < (1 << k);j ++)
if (j & (1 << i - 1))
{
a[i + (1 << k) - 1][j] = z[i];
a[j][i + (1 << k) - 1] = 0;
}
}
for (int i = 0;i < (1 << k);i ++)
{
a[i][71] = f[i];
a[71][i] = 0;
}
int ans = 0;
bool flag = false;
while (!flag)
{
flag = true;
int delta = dfs(70,2147483647);
if (delta != 0)
{
flag = false;
int i = 71;
while (i != 70)
{
int nxt = pre[i];
pre[i] = 0;
a[nxt][i] -= delta;
a[i][nxt] += delta;
i = nxt;
}
ans += delta;
}
}
if (ans != n * m)
return false;
else return true;
}
int main()
{
scanf("%d",&t);
while (t --)
{
memset(f,0,sizeof(f));
scanf("%d%d%d",&n,&m,&k);
int sum = 0;
for (int i = 1;i <= k;i ++)
{
scanf("%d%d%d",&x[i],&y[i],&z[i]);
sum += z[i];
}
if (sum < n * m)
{
printf("-1\n");
continue;
}
int l = 0;
int r = n + m;
while (l < r - 1)
{
int mid = l + r + 1 >> 1;
if (check(mid))
r = mid;
else l = mid + 1;
}
if (check(l))
printf("%d\n",l);
else printf("%d\n",r);
}
return 0;
}