社区讨论

How G

学术版参与者 3已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@m1w7gfw0
此快照首次捕获于
2024/10/05 21:43
去年
此快照最后确认于
2025/11/04 17:55
4 个月前
查看原帖
RT,意识到了这个等价于非DAG上的可相交最小路径覆盖,网络流wa了2个
CPP
#include <bitset>
#include <map>
#include <queue>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define D double
#define LD long double
#define LL long long
#define ULL unsigned long long
#define fi first
#define se second
#define mp make_pair
using namespace std;
string s[1145];
map<string, bool> M;
namespace Dinic
{
    const int N = 1e5 + 7, M = 5e6 + 7;
    const LL inf = 1e18;
    int n, S, T, h[N], hi[N], e[M], t[M], tot, d[N];
    LL mxf, f[M];
    inline void add(int x, int y, LL z, int o = 1)
    {
        e[++tot] = y, f[tot] = z, t[tot] = h[x], h[x] = tot;
        if (o)
        {
            add(y, x, 0, 0);
        }
        return;
    }
    inline bool bfs()
    {
        for (int i = 1; i <= n; i++)
        {
            d[i] = 0;
        }
        queue<int> q;
        q.push(S), d[S] = 1;
        while (q.size())
        {
            int x = q.front();
            q.pop();
            for (int i = h[x]; i; i = t[i])
            {
                int y = e[i];
                LL z = f[i];
                if (d[y] || !z)
                {
                    continue;
                }
                q.push(y);
                d[y] = d[x] + 1;
                if (y == T)
                {
                    return 1;
                }
            }
        }
        return 0;
    }
    LL dinic(int x, LL nwf)
    {
        if (x == T)
        {
            return nwf;
        }
        LL rst = nwf;
        for (int &i = hi[x]; i; i = t[i])
        {
            int y = e[i];
            LL z = f[i];
            if (d[y] != d[x] + 1 || !z)
            {
                continue;
            }
            LL k = dinic(y, min(z, rst));
            if (!k)
            {
                d[y] = 0;
            }
            else
            {
                f[i] -= k;
                f[i ^ 1] += k;
                rst -= k;
            }
            if (!rst)
            {
                break;
            }
        }
        return nwf - rst;
    }
    inline void main()
    {
        while (bfs())
        {
            for (int i = 1; i <= n; i++)
            {
                hi[i] = h[i];
            }
            LL now;
            while ((now = dinic(S, inf)))
            {
                mxf += now;
            }
        }
        return;
    }
    inline void init(int _n, int _S, int _T)
    {
        n = _n, S = _S, T = _T, tot = 1, mxf = 0;
        for (int i = 1; i <= n; i++)
        {
            h[i] = 0;
        }
        return;
    }
}
bitset<26 * 26 + 10> f[26 * 26 + 10];
int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> s[i];
        M[s[i]] = 1;
    }
    Dinic::init(2 * n + 2, 2 * n + 1, 2 * n + 2);
    for (int i = 1; i <= n; i++)
    {
        Dinic::add(2 * n + 1, i, 1);
        Dinic::add(i + n, 2 * n + 2, 1);
    }
    for (int i = 1; i <= n; i++)
    {
        // f[i][i] = 1;
        for (int j = 1; j <= n; j++)
        {
            if (i == j)
            {
                continue;
            }
            string tmp;
            tmp.push_back(s[i][1]);
            tmp.push_back(s[j][0]);
            if (M.find(tmp) != M.end())
            {
                // cout << i << ' ' << j << '\n';
                f[i][j] = 1;
            }
            else if (s[i][1] == s[j][0])
            {
                // cout << i << ' ' << j << '\n';
                f[i][j] = 1;
            }
        }
    }
    // cout << '\n';
    for (int k = 1; k <= n; ++k)
    {
        for (int i = 1; i <= n; ++i)
        {
            if (f[i][k])
            {
                f[i] |= f[k];
            }
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (i != j)
                if (f[i][j])
                {
                    // cout << i << ' ' << j << '\n';
                    Dinic::add(i, j + n, 1);
                }
        }
    }
    Dinic::main();
    cout << (n - Dinic::mxf == 0 ? 1 : n - Dinic::mxf);
    return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...