• Marriage Match II 【HDU


    题目链接

      一开始是想不断的把边插进去,然后再去考虑我们每次都加进去边权为1的边,直到跑到第几次就没法继续跑下去的这样的思路,果不其然的T了。

      然后,就是想办法咯,就想到了二分答案。

      首先,我们一开始处理关系,(一开始看错了男女关系,结局懵逼了好久),注意输入是女选男。然后,就是去处理咯,我们先要去考虑,女生之间为朋友的话,又由于朋友关系是可以推的,所以我们不妨用并查集去维护这层关系,并且把总的关系推上到并查集的根上去。

      然后,就是怎么样去想这个二分答案的过程了,我们可以假设玩了x轮,这么就代表了每个女孩纸被选择了x次,每个男孩纸也被选择了x次,(两者少了其中一者都不行)。那么,我们是不是可以从源点连到每个女孩纸的边权是x,然后从每个男孩纸连到汇点的边权是x。然后男孩、女孩之间的关系,就是我们之前并查集处理出来的了。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <limits>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #define lowbit(x) ( x&(-x) )
    #define pi 3.141592653589793
    #define e 2.718281828459045
    #define INF 0x3f3f3f3f
    #define HalF (l + r)>>1
    #define lsn rt<<1
    #define rsn rt<<1|1
    #define Lson lsn, l, mid
    #define Rson rsn, mid+1, r
    #define QL Lson, ql, qr
    #define QR Rson, ql, qr
    #define myself rt, l, r
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    const int maxN = 207, maxE = 3e4 + 7, st = 0;
    int N, M, fr, head[maxN], cur[maxN], cnt, ed, root[maxN], mod_cnt, mod_head[maxN];
    bool mp[maxN][maxN];
    int fid(int x) { return x == root[x] ? x : (root[x] = fid(root[x])); }
    struct Eddge
    {
        int nex, to, flow;
        Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), flow(c) {}
    }model[maxE], edge[maxE];
    inline void addEddge(int u, int v, int w)
    {
        edge[cnt] = Eddge(head[u], v, w);
        head[u] = cnt++;
    }
    inline void _add(int u, int v, int w) { addEddge(u, v, w); addEddge(v, u, 0); }
    int deep[maxN];
    queue<int> Q;
    inline bool bfs()
    {
        for(int i=0; i<=ed; i++) deep[i] = 0;
        while(!Q.empty()) Q.pop();
        Q.push(st); deep[st] = 1;
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop();
            for(int i=head[u], v, f; ~i; i=edge[i].nex)
            {
                v = edge[i].to; f = edge[i].flow;
                if(f && !deep[v])
                {
                    deep[v] = deep[u] + 1;
                    Q.push(v);
                }
            }
        }
        return deep[ed];
    }
    inline int dfs(int u, int dist)
    {
        if(u == ed) return dist;
        for(int &i=cur[u], v, f; ~i; i=edge[i].nex)
        {
            v = edge[i].to; f = edge[i].flow;
            if(f && deep[v] == deep[u] + 1)
            {
                int di = dfs(v, min(dist, f));
                if(di)
                {
                    edge[i].flow -= di;
                    edge[i^1].flow += di;
                    return di;
                }
            }
        }
        return 0;
    }
    inline int Dinic()
    {
        int ans = 0, tmp;
        while(bfs())
        {
            for(int i=0; i<=ed; i++) cur[i] = head[i];
            while((tmp = dfs(st, INF))) ans += tmp;
        }
        return ans;
    }
    struct Query
    {
        int u, v;
        Query(int a=0, int b=0):u(a), v(b) {}
    }qes[10004];
    inline void init()
    {
        cnt = 0; ed = (N<<1) + 1;
        memset(head, -1, sizeof(head));
        for(int i=1; i<=N; i++) root[i] = i;
        for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) mp[i][j] = false;
    }
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d%d", &N, &M, &fr);
            init();
            for(int i=1, u, v; i<=M; i++)
            {
                scanf("%d%d", &u, &v);
                mp[u][v] = true;
            }
            for(int i=1, u, v, fu, fv; i<=fr; i++)
            {
                scanf("%d%d", &u, &v);
                fu = fid(u); fv = fid(v);
                if(fu == fv) continue;
                root[fu] = fv;
                for(int j=1; j<=N; j++)
                {
                    if(mp[fu][j] && !mp[fv][j]) mp[fv][j] = true;
                }
            }
            for(int i=1, u; i<=N; i++)
            {
                u = fid(i);
                for(int j=1; j<=N; j++)
                {
                    if(mp[u][j]) _add(i, j + N, 1);
                }
            }
            mod_cnt = cnt;
            for(int i=0; i<cnt; i++) model[i] = edge[i];
            for(int i=0; i<=ed; i++) mod_head[i] = head[i];
            int ans = 0, l = 0, r = N, mid = 0;
            while(l <= r)
            {
                mid = (l + r) >> 1;
                cnt = mod_cnt;
                for(int i=0; i<cnt; i++) edge[i] = model[i];
                for(int i=0; i<=ed; i++) head[i] = mod_head[i];
                for(int i=1; i<=N; i++)
                {
                    _add(st, i, mid);
                    _add(i + N, ed, mid);
                }
                if(Dinic() >= N * mid)
                {
                    ans = mid;
                    l = mid + 1;
                }
                else r = mid - 1;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    判断日期是否是法定节假日或者休息日
    linux版powershell安装教程(.net core版)
    两款【linux字符界面下】显示【菜单】,【选项】的powershell脚本模块介绍
    powershell中使用超大内存对象
    powershell脚本,命令行参数传值,并绑定变量的例子
    在docker容器中安装和使用,linux版的powershell
    powershell开源新闻及简介
    用powershell+excel行列转置三步走
    让powershell同时只能运行一个脚本(进程互斥例子)
    powershell玩转SQL SERVER所有版本
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/11254177.html
Copyright © 2020-2023  润新知