网络流题解

P3376 【模板】网络最大流

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200+10,INF=0x3f3f3f3f;
int head[N];
struct e
{
    int to;
    ll f;
    int ne;
} edge[10010];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
ll dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    ll flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            ll tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
ll dinic(int s, int t)
{
    ll ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    head[0] = 1;
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    for (int i = 1; i <= m;i++)
    {
        int u, v, f;
        cin >> u >> v >> f;
        add(u, v, f);
    }
    cout << dinic(s, t);
    return 0;
}

P3381【模板】最小费用最大流

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=6e3+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N];
struct e
{
    int to, f, c, ne;
} edge[N * 10 * 2];
int dis[N], pre[N], prv[N];//最小费用路径,前驱节点,前驱边
bool vis[N];
void add(int u, int v, int f,int c)
{
    edge[++head[0]] = {v, f, c, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, -c, head[v]};
    head[v] = head[0];
}
bool spfa(int s,int t)
{
    queue<int> que;
    que.emplace(s);
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    vis[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for (int i = head[u]; i;i = edge[i].ne)
        {
            int v = edge[i].to;
            if(edge[i].f && dis[v] > dis[u] + edge[i].c)
            {
                dis[v] = dis[u] + edge[i].c;
                prv[v] = u;
                pre[v] = i;
                if(!vis[v])
                {
                    vis[v] = 1;
                    que.emplace(v);
                }
            }
        }
    }
    return dis[t] != INF;
}
pii mcmf(int s,int t)//时间复杂度O(V^2 E^2),实际情况远小于理论时间复杂度
{
    int cost = 0, flow = 0;
    while(spfa(s,t))
    {
        int mn = INF;
        for (int i = t; i != s; i = prv[i])
        {
            mn = min(mn, edge[pre[i]].f);
        }
        flow += mn;
        cost += mn * dis[t];
        for (int i = t; i != s;i = prv[i])
        {
            edge[pre[i]].f -= mn;
            edge[pre[i] ^ 1].f += mn;//反向边
        }
    }
    return {cost, flow};
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    head[0] = 1;
    for (int i = 1; i <= m;i++)
    {
        int u, v, f, c;
        cin >> u >> v >> f >> c;
        add(u, v, f, c);
    }
    pii ans = mcmf(s, t);
    cout << ans.second << ' ' << ans.first;
    return 0;
}

P2756 飞行员配对方案问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e2+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N];
struct e
{
    int to, f, ne;
}edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> m >> n;
    head[0] = 1;
    int s = n + 1, t = n + 2;
    int u, v;
    for (int i = 1; i <= m;i++)
    {
        add(s, i, 1);
    }
    while(cin>>u>>v)
    {
        if(u==-1)
            break;
        add(u, v, 1);
    }
    for (int i = m + 1; i <= n;i++)
    {
        add(i, t, 1);
    }
    int ans = dinic(s, t);
    cout << ans <<'\n';
    for (int i = 1; i <= m;i++)
    {
        int v = 0;
        for (int j = head[i]; j;j = edge[j].ne)
        {
            int to = edge[j].to;
            if(to>m && to<=n && edge[j].f == 0)
            {
                v = to;
                break;
            }
        }
        if(v)
        {
            cout << i << " " << v << '\n';
        }
    }
        return 0;
}

P3254 圆桌问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=500+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N];
struct e
{
    int to, f, ne;
} edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    head[0] = 1;
    int n, m, s, t;
    cin >> m >> n;
    int sum = 0;
    s = n + m + 1, t = s + 1;
    for (int i = 1; i <= m;i++)
    {
        int num;
        cin >> num;
        sum += num;
        add(s, i, num);
    }
    for (int i = 1; i <= n;i++)
    {
        int num;
        cin >> num;
        add(i + m, t, num);
        for (int j = 1; j <= m;j++)
        {
            add(j, i + m, 1);
        }
    }
    int ans = dinic(s, t);
    if(ans!=sum)
    {
        cout << 0;
    }
    else
    {
        cout << 1 << '\n';
        for (int i = 1; i <= m;i++)
        {
            int v = -1;
            for (int j = head[i]; j;j = edge[j].ne)
            {
                if(edge[j].f==0&&edge[j].to<s)
                {
                    cout << edge[j].to - m << ' ';
                }
            }
            cout << '\n';
        }
    }
    return 0;
}

P3171 [CQOI2015]网络吞吐量

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
const int N = 2e3 + 10;
const ll INF = 1e18;
const double eps=1e-8;
int head[N];
struct e
{
    int to;
    ll f;
    int ne;
} edge[200010];
void add(int u, int v, ll f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
ll dfs(int u ,int t, ll f)
{
    if(!f || u==t)
        return f;

    ll flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            ll tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
ll dinic(int s, int t)
{
    ll ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
bool vis[N];
ll dis[N];
vector<pair<int, ll>> p[N];
void spfa()
{
    for (int i = 1; i < N;i++)
    {
        dis[i] = INF;
    }
    queue<int> que;
    que.push(1);
    dis[1] = 0;
    vis[1] = 1;
    while(!que.empty())
    {
        int t = que.front();
        que.pop();
        vis[t] = 0;
        for(auto tt : p[t])
        {
            int j = tt.first;
            ll w = tt.second;
            if(dis[j] > dis[t] + w)
            {
                dis[j] = dis[t] + w;
                if(!vis[j])
                {
                    que.push(j);
                    vis[j] = 1;
                }
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    head[0] = 1;
    int s = n * 2 + 1;
    int t = s + 1;
    for (int i = 1; i <= m;i++)
    {
        int u, v;
        ll f;
        cin >> u >> v >> f;
        p[u].push_back({v, f});
        p[v].push_back({u, f});
    }
    spfa();
    for (int i = 1; i <= n;i++)
    {
        ll f;
        cin >> f;
        if(i!=1&&i!=n)
            add(i, i + n, f);//入 -> 出
        else
            add(i, i + n, INF);
    }
    add(s, 1, INF);
    add(n + n, t, INF);
    for (int i = 1; i <= n;i++)
    {
        for(auto t : p[i])
        {
            int j = t.first;
            ll w = t.second;
            if(dis[j] == dis[i] + w)
            {
                add(i + n, j, INF);
            }
        }
    }
    cout << dinic(s,t);
    return 0;
}

P2766 最长不下降子序列问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2000+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int a[N],dp[N];
int head[N];
struct e
{
    int to, f, ne;
} edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    static int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
void init()
{
    memset(head, 0, sizeof head);
    head[0] = 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    head[0] = 1;
    for (int i = 1; i <= n;i++)
    {
        dp[i] = 1;
        cin >> a[i];
    }
    for (int i = 1; i <= n;i++)
    {
        for (int j = 1; j < i;j++)
        {
            if(a[i]>=a[j])
                dp[i] = max(dp[i],dp[j] + 1);
        }
    }
    int len = 0;
    for (int i = 1; i <= n;i++)
        len = max(len, dp[i]);
    cout << len << '\n';
    int s = n*2 + 1, t = s + 1;
    for (int i = 1; i <= n;i++)
    {
        if(dp[i]==len)
        {
            add(i+n, t, 1);
        }
        if(dp[i]==1)
        {
            add(s, i, 1);
        }
        add(i, i + n, 1);
    }
    for (int i = 1; i < n;i++)
    {
        for (int j = i + 1; j <= n;j++)
        {
            if((a[j] >= a[i])&&(dp[j] == dp[i] + 1))
                add(i + n, j, 1);
        }
    }
    cout << dinic(s, t) << '\n';
    if(n==1)
    {
        cout << 1;
        return 0;
    }
    add(s, 1, INF);
    add(1, 1 + n, INF);
    if (dp[n] == len)
        add(n, n + n, INF), add(n + n, t, INF);
    cout << dinic(s, t) << '\n';
    return 0;
}

P5771 反质数序列

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
const int N=3000+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N];
struct e
{
    int to, f, ne;
} edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
void init()
{
    memset(head, 0, sizeof head);
    head[0] = 1;
}
vector<pii> odd, even;
bool prime(int x)
{
    if(x == 2)
        return 1;
    for (int i = 2; i <= x / i;i++)
    {
        if(x % i==0)
            return 0;
    }
    return 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    head[0] = 1;
    int ans = n, f = 0;
    int s = n + 1, t = s + 1;
    for (int i = 1; i <= n;i++)
    {
        int x;
        cin >> x;
        if(x == 1 && f)
        {
            ans--;
            continue;
        }
        if(x == 1)
            f = 1;
        if(x&1)
            odd.push_back({x, i}), add(s, i, 1);
        else
            even.push_back({x, i}),add(i, t, 1);
    }
    for (int i = 0; i < odd.size();i++)
    {
        for (int j = 0; j < even.size();j++)
        {
            if(prime(odd[i].first + even[j].first))
                add(odd[i].second, even[j].second, INF);
        }
    }
    cout << ans - dinic(s, t);
    return 0;
}

P3163 危桥

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
const int N=500+10,INF=0x3f3f3f3f;
const double eps=1e-8;
char a[55][55];
int head[N];
struct e
{
    int to, f, ne;
} edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
void init()
{
    memset(head, 0, sizeof head);
    head[0] = 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, a1, b1, a2, b2, an, bn;
    while(cin>>n>>a1>>a2>>an>>b1>>b2>>bn)
    {
        init();
        a1++, a2++, b1++, b2++;
        for (int i = 1; i <= n;i++)
        {
            for (int j = 1; j <= n;j++)
            {
                cin >> a[i][j];
            }
        }
        int s = n + 1;
        int t = s + 1;
        for (int i = 1; i <= n;i++)
        {
            for (int j = 1; j <= n;j++)
            {
                if(a[i][j]=='N')
                    add(i, j, INF);
                if(a[i][j]=='O')
                    add(i, j, 2);
            }
        }
        add(s, a1, 2*an);
        add(s, b1, 2*bn);
        add(a2, t, 2*an);
        add(b2, t, 2*bn);
        if (dinic(s, t) == 2 * (an + bn))
        {
            init();
            swap(b1, b2);
            for (int i = 1; i <= n; i++)
            {
                for (int j = 1; j <= n; j++)
                {
                    if (a[i][j] == 'N')
                        add(i, j, INF);
                    if (a[i][j] == 'O')
                        add(i, j, 2);
                }
            }
            add(s, a1, 2 * an);
            add(s, b1, 2 * bn);
            add(a2, t, 2 * an);
            add(b2, t, 2 * bn);
            if (dinic(s, t) == 2 * (an + bn))
                cout << "Yes\n";
            else
                cout << "No\n";
        }
        else
            cout << "No\n";
    }
    return 0;
}

P5038 奇怪的游戏

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define int ll
#define INF 9e18
const int N = 1600 + 10;
const double eps=1e-8;
int head[N];
int n, m, S, T;
struct e
{
    int to;
    int f;
    int ne;
} edge[10*N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
void init()
{
    memset(head, 0, sizeof head);
    head[0] = 1;
}
int a[50][50];
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
bool check(int mid)
{
    init();
    int res = 0;
    for (int i = 1;i<=n;i++)
    {
        for (int j = 1; j <= m;j++)
        {
            if((i + j&1))
            {
                add(S, (i - 1) * m + j, mid - a[i][j]);
                for (int k = 0; k < 4;k++)
                {
                    int x = i + dx[k];
                    int y = j + dy[k];
                    if(x>=1&&x<=n&&y>=1&&y<=m)
                    {
                        add((i - 1) * m + j, (x - 1) * m + y, INF);
                    }
                }
            }
            else
            {
                add((i - 1) * m + j, T, mid - a[i][j]);
                res += mid - a[i][j];
            }
        }
    }
    return dinic(S,T) == res;
}
signed main()
{
    // ios::sync_with_stdio(false);
    // cin.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        init();
        scanf("%lld%lld", &n, &m);
        int sum1 = 0, sum2 = 0;
        int cnt1 = 0, cnt2 = 0;
        S = n*m+1, T = S + 1;
        int mmax = -1;
        for (int i = 1; i <= n;i++)
        {
            for (int j = 1; j <= m;j++)
            {
                scanf("%lld", &a[i][j]);
                if ((i + j) & 1)
                    sum1 += a[i][j], cnt1++;
                else
                    sum2 += a[i][j], cnt2++;
                mmax = max(a[i][j], mmax);
            }
        }
        if((n*m)%2==0)
        {
            if(sum1!=sum2)
            {
                printf("-1\n");
                continue;
            }
            int l = mmax, r = 10 * mmax;
            while(l < r)
            {
                int mid = l + r >> 1;
                if(check(mid))
                    r = mid;
                else
                    l = mid + 1;
            }
            if(!check(r))
            {
                printf("-1\n");
                continue;
            }
            int ans = 0;
            for (int i = 1; i <= n;i++)
            {
                for (int j = 1; j <= m;j++)
                {
                    ans += r - a[i][j];
                }
            }
            printf("%lld\n",ans / 2);
        }
        else
        {
            if((sum2 - sum1)%(cnt2 - cnt1))
            {
                printf("-1\n");
                continue;
            }
            int x = (sum2 - sum1) / (cnt2 - cnt1);
            if(x < mmax)
            {
                printf("-1\n");
                continue;
            }
            if(check(x))
            {
                printf("%lld\n", x * cnt1 - sum1);
            }
            else
                printf("-1\n");
        }
    }

    return 0;
}

P4016 负载平衡问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int a[N];
int head[N];
struct e
{
    int to, f, c, ne;
} edge[N * 10 * 2];
int dis[N], pre[N], prv[N];//最小费用路径,前驱节点,前驱边
bool vis[N];
void add(int u, int v, int f,int c)
{
    edge[++head[0]] = {v, f, c, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, -c, head[v]};
    head[v] = head[0];
}
bool spfa(int s,int t)
{
    queue<int> que;
    que.emplace(s);
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    vis[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for (int i = head[u]; i;i = edge[i].ne)
        {
            int v = edge[i].to;
            if(edge[i].f && dis[v] > dis[u] + edge[i].c)
            {
                dis[v] = dis[u] + edge[i].c;
                prv[v] = u;
                pre[v] = i;
                if(!vis[v])
                {
                    vis[v] = 1;
                    que.emplace(v);
                }
            }
        }
    }
    return dis[t] != INF;
}
pii mcmf(int s,int t)//时间复杂度O(V^2 E^2),实际情况远小于理论时间复杂度
{
    int cost = 0, flow = 0;
    while(spfa(s,t))
    {
        int mn = INF;
        for (int i = t; i != s; i = prv[i])
        {
            mn = min(mn, edge[pre[i]].f);
        }
        flow += mn;
        cost += mn * dis[t];
        for (int i = t; i != s;i = prv[i])
        {
            edge[pre[i]].f -= mn;
            edge[pre[i] ^ 1].f += mn;//反向边
        }
    }
    return {cost, flow};
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    head[0] = 1;
    int n;
    cin >> n;
    int s = n + 1, t = s + 1;
    int sum = 0;
    for (int i = 1; i <= n;i++)
    {
        cin >> a[i];
        sum += a[i];
        add(s, i, a[i], 0);
    }
    int ave = sum / n;
    for (int i = 1; i <= n;i++)
    {
        add(i, t, ave, 0);
        if(i-1>0)
        {
            add(i, i - 1, INF, 1);
        }
        if(i+1<=n)
        {
            add(i, i + 1, INF, 1);
        }
    }
    add(1, n, INF, 1);
    add(n, 1, INF, 1);

    cout << mcmf(s, t).first;
    return 0;
}

P4015 运输问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=100+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int a[N],b[N],c[N][N];
int head[N];
struct e
{
    int to, f, c, ne;
} edge[N * 10 * 2];
int dis[N], pre[N], prv[N];//最小费用路径,前驱节点,前驱边
bool vis[N];
void add(int u, int v, int f, int c)
{
    edge[++head[0]] = {v, f, c, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, -c, head[v]};
    head[v] = head[0];
}
bool spfa(int s,int t)
{
    queue<int> que;
    que.emplace(s);
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    vis[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for (int i = head[u]; i;i = edge[i].ne)
        {
            int v = edge[i].to;
            if(edge[i].f && dis[v] > dis[u] + edge[i].c)
            {
                dis[v] = dis[u] + edge[i].c;
                prv[v] = u;
                pre[v] = i;
                if(!vis[v])
                {
                    vis[v] = 1;
                    que.emplace(v);
                }
            }
        }
    }
    return dis[t] != INF;
}
pii mcmf(int s,int t)//时间复杂度O(V^2 E^2),实际情况远小于理论时间复杂度
{
    int cost = 0, flow = 0;
    while(spfa(s,t))
    {
        int mn = INF;
        for (int i = t; i != s; i = prv[i])
        {
            mn = min(mn, edge[pre[i]].f);
        }
        flow += mn;
        cost += mn * dis[t];
        for (int i = t; i != s;i = prv[i])
        {
            edge[pre[i]].f -= mn;
            edge[pre[i] ^ 1].f += mn;//反向边
        }
    }
    return {cost, flow};
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    head[0] = 1;
    int m, n;
    cin >> m >> n;
    int s = m + n + 1, t = s + 1;
    for (int i = 1; i <= m;i++)
    {
        cin >> a[i];
        add(s, i, a[i], 0);
    }
    for (int i = 1; i <= n;i++)
    {
        cin >> b[i];
        add(i + m, t, b[i], 0);
    }
    for (int i = 1; i <= m;i++)
    {
        for (int j = 1; j <= n;j++)
        {
            cin >> c[i][j];
            add(i, j + m, INF, c[i][j]);
        }
    }
    cout << mcmf(s, t).first << '\n';
    memset(head, 0, sizeof head);
    memset(pre, 0, sizeof pre);
    memset(prv, 0, sizeof prv);
    head[0] = 1;
    for (int i = 1; i <= m;i++)
    {
        add(s, i, a[i], 0);
    }
    for (int i = 1; i <= n;i++)
    {
        add(i + m, t, b[i], 0);
    }
    for (int i = 1; i <= m;i++)
    {
        for (int j = 1; j <= n;j++)
        {
            add(i, j + m, INF, -c[i][j]);
        }
    }
    cout << -mcmf(s, t).first;
    return 0;
}

P1251 餐巾计划问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=4000+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N];
int a[N];
struct e
{
    int to, f, c, ne;
} edge[N * 10 * 2];
int dis[N], pre[N], prv[N];//最小费用路径,前驱节点,前驱边
bool vis[N];
void add(int u, int v, int f, int c)
{
    edge[++head[0]] = {v, f, c, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, -c, head[v]};
    head[v] = head[0];
}
bool spfa(int s,int t)
{
    queue<int> que;
    que.emplace(s);
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    vis[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for (int i = head[u]; i;i = edge[i].ne)
        {
            int v = edge[i].to;
            if(edge[i].f && dis[v] > dis[u] + edge[i].c)
            {
                dis[v] = dis[u] + edge[i].c;
                prv[v] = u;
                pre[v] = i;
                if(!vis[v])
                {
                    vis[v] = 1;
                    que.emplace(v);
                }
            }
        }
    }
    return dis[t] != INF;
}
ll mcmf(int s,int t)//时间复杂度O(V^2 E^2),实际情况远小于理论时间复杂度
{
    ll cost = 0;
    while(spfa(s,t))
    {
        int mn = INF;
        for (int i = t; i != s; i = prv[i])
        {
            mn = min(mn, edge[pre[i]].f);
        }
        cost += 1ll*mn * dis[t];
        for (int i = t; i != s;i = prv[i])
        {
            edge[pre[i]].f -= mn;
            edge[pre[i] ^ 1].f += mn;//反向边
        }
    }
    return cost;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    head[0] = 1;
    int n;
    cin>>n;
    for (int i = 1; i <= n;i++)
    {
        cin >> a[i];
    }
    int s = n * 2 + 1, t = s + 1;
    int p, m, f, n1, s1;
    cin >> p >> m >> f >> n1 >> s1;
    for (int i = 1; i <= n;i++)
    {
        add(s, i, INF, p);
        add(i, t, a[i], 0);
        add(s, i + n, a[i], 0);
        if(i+m<=n)
            add(i + n, i + m, INF, f);
        if(i+n1<=n)
            add(i + n, i + n1, INF, s1);
        if(i!=n)
            add(i + n, i + n + 1, INF, 0);
    }
    cout << mcmf(s, t);
    return 0;
}

P4013 数字梯形问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2000+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int a[N][N],id[N][N];
int head[N];
struct e
{
    int to, f, c, ne;
} edge[N * 10 * 2];
int dis[N], pre[N], prv[N];//最小费用路径,前驱节点,前驱边
bool vis[N];
void add(int u, int v, int f, int c)
{
    edge[++head[0]] = {v, f, c, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, -c, head[v]};
    head[v] = head[0];
}
bool spfa(int s,int t)
{
    queue<int> que;
    que.emplace(s);
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    vis[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for (int i = head[u]; i;i = edge[i].ne)
        {
            int v = edge[i].to;
            if(edge[i].f && dis[v] > dis[u] + edge[i].c)
            {
                dis[v] = dis[u] + edge[i].c;
                prv[v] = u;
                pre[v] = i;
                if(!vis[v])
                {
                    vis[v] = 1;
                    que.emplace(v);
                }
            }
        }
    }
    return dis[t] != INF;
}
int mcmf(int s,int t)//时间复杂度O(V^2 E^2),实际情况远小于理论时间复杂度
{
    int cost = 0, flow = 0;
    while(spfa(s,t))
    {
        int mn = INF;
        for (int i = t; i != s; i = prv[i])
        {
            mn = min(mn, edge[pre[i]].f);
        }
        flow += mn;
        cost += mn * dis[t];
        for (int i = t; i != s;i = prv[i])
        {
            edge[pre[i]].f -= mn;
            edge[pre[i] ^ 1].f += mn;//反向边
        }
    }
    return cost;
}
void init()
{
    memset(head, 0, sizeof head);
    memset(pre, 0, sizeof pre);
    memset(prv, 0, sizeof prv);
    head[0] = 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int m,n;
    cin>>m>>n;
    int sum = 0;
    int s, t;
    head[0] = 1;
    for (int i = 1; i <= n;i++)
    {
        for (int j = 1; j <= m + i - 1;j++)
        {
            cin>>a[i][j];
            id[i][j]=++sum;
        }
    }
    s = sum*2 + 1, t = s + 1;
    for (int i = 1; i < n;i++)
    {
        for (int j = 1; j <= m + i - 1;j++)
        {
            if(i==1)
                add(s, id[i][j], 1, 0);
            add(id[i][j], id[i][j] + sum, 1, -a[i][j]);
            add(id[i][j] + sum, id[i + 1][j], 1, 0);
            add(id[i][j] + sum, id[i + 1][j + 1], 1, 0);
        }
    }
    for (int j = 1; j <= m + n - 1;j++)
    {
        add(id[n][j] + sum, t, 1, 0);
        add(id[n][j], id[n][j] + sum, 1, -a[n][j]);
    }
    cout << -mcmf(s, t) << '\n';
    init();
    s = sum + 1, t = s + 1;
    for (int i = 1; i < n;i++)
    {
        for (int j = 1; j <= m + i - 1;j++)
        {
            if(i==1)
                add(s, id[i][j], 1, 0);
            add(id[i][j], id[i + 1][j], 1, -a[i][j]);
            add(id[i][j], id[i + 1][j + 1], 1, -a[i][j]);
        }
    }
    for (int j = 1; j <= m + n - 1;j++)
    {
        add(id[n][j], t, INF, -a[n][j]);
    }
    cout << -mcmf(s, t) << '\n';
    init();
    s = sum + 1, t = s + 1;
    for (int i = 1; i < n;i++)
    {
        for (int j = 1; j <= m + i - 1;j++)
        {
            if(i==1)
                add(s, id[i][j], 1, 0);
            add(id[i][j], id[i + 1][j], INF, -a[i][j]);
            add(id[i][j], id[i + 1][j + 1], INF, -a[i][j]);
        }
    }
    for (int j = 1; j <= m + n - 1;j++)
    {
        add(id[n][j], t, INF, -a[n][j]);
    }
    cout << -mcmf(s, t) << '\n';
    return 0;
}

P3356 火星探险问题

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 3000 + 10, INF = 0x3f3f3f3f;
const double eps = 1e-8;
int head[N], a[40][40], id[40][40], s, t;
int n, p, q;
struct e
{
    int to, f, c, ne;
} edge[N * 10 * 2];
int dis[N], pre[N], prv[N]; //最小费用路径,前驱节点,前驱边
bool vis[N];
void add(int u, int v, int f, int c)
{
    edge[++head[0]] = {v, f, c, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, -c, head[v]};
    head[v] = head[0];
}
bool spfa(int s, int t)
{
    queue<int> que;
    que.emplace(s);
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    vis[s] = 1;
    while (!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for (int i = head[u]; i; i = edge[i].ne)
        {
            int v = edge[i].to;
            if (edge[i].f && dis[v] > dis[u] + edge[i].c)
            {
                dis[v] = dis[u] + edge[i].c;
                prv[v] = u;
                pre[v] = i;
                if (!vis[v])
                {
                    vis[v] = 1;
                    que.emplace(v);
                }
            }
        }
    }
    return dis[t] != INF;
}
pii mcmf(int s, int t) //时间复杂度O(V^2 E^2),实际情况远小于理论时间复杂度
{
    int cost = 0, flow = 0;
    while (spfa(s, t))
    {
        int mn = INF;
        for (int i = t; i != s; i = prv[i])
        {
            mn = min(mn, edge[pre[i]].f);
        }
        flow += mn;
        cost += mn * dis[t];
        for (int i = t; i != s; i = prv[i])
        {
            edge[pre[i]].f -= mn;
            edge[pre[i] ^ 1].f += mn; //反向边
        }
    }
    return {cost,flow};
}
void print(int x, int y, int u, int k)
{
    int dx, dy, mov;
    for (int i = head[u]; i;i = edge[i].ne)
    {
        int to = edge[i].to;
        if(to == s||to == t||to == u - p*q||edge[i^1].f==0)
            continue;
        edge[i ^ 1].f--;
        if(to>p*q)
        {
            print(x, y, to, k);
            return;
        }
        if(to == id[x][y] + 1)
        {
            dx = x;
            dy = y + 1;
            mov = 1;
        }
        else
            dx = x + 1, dy = y, mov = 0;
        cout << k << ' ' << mov << '\n';
        print(dx, dy, to + p * q, k);
        return;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    head[0] = 1;
    cin >> n >> q >> p;
    int sum = 0;
    for (int i = 1; i <= p; i++)
    {
        for (int j = 1; j <= q; j++)
        {
            cin >> a[i][j];
            id[i][j] = ++sum;
        }
    }
    for (int i = 1; i <= p; i++)
    {
        for (int j = 1; j <= q; j++)
        {
            if (a[i][j] == 1)
                continue;
            if (a[i][j] == 2)
            {
                add(id[i][j], id[i][j] + sum, 1, -1); //拆点
            }
            add(id[i][j], id[i][j] + sum, INF, 0);
            if (i < p && a[i + 1][j] != 1)
                add(id[i][j] + sum, id[i + 1][j], INF, 0);
            if (j < q && a[i][j + 1] != 1)
                add(id[i][j] + sum, id[i][j + 1], INF, 0);
        }
    }
    s = sum * 2 + 1, t = s + 1;
    add(s, 1, n, 0);
    add(id[p][q] + sum, t, n, 0);
    pii ans = mcmf(s, t);
    int flow = ans.second;
    for (int i = 1; i <= flow; i++)
    {
        print(1, 1, 1, i);
    }
    return 0;
}

P2774 方格取数问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e4+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int a[105][105],id[105][105], dx[]={1,-1,0,0},dy[]={0,0,1,-1};
int n, m;
bool check(int x,int y)
{
    return x >= 1 && x <= n && y >= 1 && y <= m;
}
int head[N];
struct e
{
    int to, f, ne;
} edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    int sum = 0;
    int cnt = 0;
    head[0] = 1;
    for (int i = 1; i <= n;i++)
    {
        for (int j = 1; j <= m;j++)
        {
            cin >> a[i][j];
            sum += a[i][j];
            id[i][j] = ++cnt;
        }
    }
    int s = n*m + 1, t = s + 1;
    for (int i = 1;i<=n;i++)
    {
        for (int j = 1; j <= m;j++)
        {
            if((i+j)%2==0)
            {
                add(s, id[i][j], a[i][j]);

                for (int k = 0; k < 4;k++)
                {
                    int x = i + dx[k];
                    int y = j + dy[k];
                    if(check(x,y))
                    {
                        add(id[i][j], id[x][y], INF);
                    }
                }
            }
            else
            {
                add(id[i][j], t, a[i][j]);
            }
        }
    }
    int ans = dinic(s, t);
    cout << sum - ans;
    return 0;
}

P3355 骑士共存问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=4e4+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int a[205][205],id[205][205], dx[]={1,1,-1,-1,2,2,-2,-2},dy[]={2,-2,2,-2,1,-1,1,-1};
int n, m;
bool check(int x,int y)
{
    return x >= 1 && x <= n && y >= 1 && y <= n;
}
int head[N];
struct e
{
    int to, f, ne;
} edge[N*1000];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    int sum = n * n;
    int cnt = 0;
    head[0] = 1;
    for (int i = 1; i <= m;i++)
    {
        int x, y;
        cin >> x >> y;
        a[x][y] = 1;
    }
    for (int i = 1; i <= n;i++)
    {
        for (int j = 1; j <= n;j++)
        {
            id[i][j] = ++cnt;
        }
    }
    int s = n*n + 1, t = s + 1;
    for (int i = 1;i<=n;i++)
    {
        for (int j = 1; j <= n;j++)
        {
            if(a[i][j])
                continue;
            if((i+j)&1)
            {
                add(s, id[i][j], 1);

                for (int k = 0; k < 8;k++)
                {
                    int x = i + dx[k];
                    int y = j + dy[k];
                    if(check(x,y)&&!a[x][y])
                    {
                        add(id[i][j], id[x][y], INF);
                    }
                }
            }
            else
            {
                add(id[i][j], t, 1);
            }
        }
    }
    int ans = dinic(s, t);
    cout << sum - ans - m;
    return 0;
}

P2765 魔术球问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
const int N=10000+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N], s, t, n;
bool vis[N];
struct e
{
    int to, f, ne;
} edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    static int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
void print(int x)
{
    vis[x] = 1;
    cout << x << ' ';
    for (int i = head[x]; i;i = edge[i].ne)
    {
        int to = edge[i].to;
        int f = edge[i].f;
        if(!f&&to!=s&&to>n&&to!=t&to!=s)
        {
            print(to - 5000);
            break;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    int cnt = 0;
    head[0] = 1;
    vector<int> nums;
    int pos = 0;
    s = 5000 + 1;
    t = s + 1;
    int ans = 1;
    int num = 0;
    while(cnt <= n)
    {
        pos++;
        add(s, pos, 1);
        add(pos + 5000, t, 1);
        for (int i = 0; i < nums.size();i++)
        {
            int res = sqrt(nums[i] + pos);
            if((res * res) == (nums[i] + pos))
            {
                add(nums[i], pos + 5000, 1);
            }
        }
        nums.push_back(pos);
        //cout << dinic(s, t) << '\n';
        int res = dinic(s, t);
        if(res == ans)
        {
            cnt++;
        }
        ans = res;
    }
    cout << pos - 1 << '\n';
    for (int i = 1; i <= pos - 1;i++)
    {
        if(!vis[i])
        {
            print(i);
            cout << '\n';
        }
    }
    return 0;
}

P2057 善意的投票

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
const int N=500+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N];
struct e
{
    int to, f, ne;
} edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
void init()
{
    memset(head, 0, sizeof head);
    head[0] = 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    head[0] = 1;
    int s = n + 1;
    int t = s + 1;
    for (int i = 1; i <= n;i++)
    {
        int x;
        cin>>x;
        if(x)
            add(s, i, 1);
        else
            add(i, t, 1);
    }
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        add(x, y, 1);
        add(y, x, 1);
    }
    cout << dinic(s, t);
    return 0;
}

P4174 最大获利

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
const int N=55000+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N];
struct e
{
    int to, f, ne;
} edge[10*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
void init()
{
    memset(head, 0, sizeof head);
    head[0] = 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    head[0] = 1;
    cin >> n >> m;
    int s = n + m + 1;
    int t = s + 1;
    for (int i = 1; i <= n;i++)
    {
        int x;
        cin >> x;
        add(s, i, x);
    }
    int sum = 0;
    for (int i = 1; i <= m;i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        sum += w;
        add(u, i + n, INF);
        add(v, i + n, INF);
        add(i + n, t, w);
    }
    cout << sum - dinic(s, t);
    return 0;
}

P2764 最小路径覆盖问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
const int N=300+10,INF=0x3f3f3f3f;
const double eps=1e-8;
int head[N],fa[N],vis[N];
int n, m, s, t;
struct e
{
    int to, f, ne;
} edge[N*N];
void add(int u, int v, int f)
{
    edge[++head[0]] = {v, f, head[u]};
    head[u] = head[0];
    edge[++head[0]] = {u, 0, head[v]};//反向边
    head[v] = head[0];
}
int dep[N], cur[N];
bool bfs(int s,int t)
{
    memset(dep, 0, sizeof dep);
    memcpy(cur, head, sizeof cur);
    queue<int> que;
    que.emplace(s);
    dep[s] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = head[u]; i;i = edge[i].ne)
        {
            if(edge[i].f && !dep[edge[i].to])
            {
                dep[edge[i].to] = dep[u] + 1;
                que.emplace(edge[i].to);
            }
        }
    }
    return dep[t];
}
int dfs(int u ,int t, int f)
{
    if(!f || u==t)
        return f;

    int flow = 0;
    for (int i = cur[u]; flow < f && i; i = edge[i].ne)
    {
        cur[u] = i;//弧优化
        if(edge[i].f && dep[edge[i].to] == dep[u] + 1)
        {
            int tmp = dfs(edge[i].to, t, min(f - flow, edge[i].f));
            edge[i].f -= tmp;
            edge[i ^ 1].f += tmp;//反向边
            flow += tmp;
        }
    }
    return flow;
}
int dinic(int s, int t)
{
    int ans = 0;
    while(bfs(s,t))//找增广路
    {
        ans += dfs(s, t, INF);
    }
    return ans;
}
void print(int x)
{
    vis[x] = 1;
    cout << x << ' ';
    for (int j = head[x]; j;j = edge[j].ne)
    {
        int to = edge[j].to;
        int f = edge[j].f;
        if(!f&&to!=t&&to!=s&&!vis[to - n])
        {
            print(to - n);
            break;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    s = (n << 1) + 1;
    t = s + 1;
    head[0] = 1;
    for (int i = 1; i <= n;i++)
    {

        add(s, i, 1);
        add(i + n, t, 1);
    }
    for (int i = 1; i <= m;i++)
    {
        int a,b;
        cin>>a>>b;
        add(a, b + n, 1);
    }
    int ans = n - dinic(s, t);
    for (int i = 1; i <= n;i++)
    {
        if(!vis[i])
        {
            print(i);
            cout << '\n';
        }
    }
    cout << ans;
    return 0;
}
posted @ 2022-11-08 21:06  menitrust  阅读(34)  评论(0编辑  收藏  举报