【百度之星2020】Mosquito 解题报告

题目链接: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;
}

你可能感兴趣的:(网络流)