N - Marriage Match II - HDU 3081(最大流)

题目大意:有一些男孩和女孩玩一个游戏,每个女孩都可以挑一个男孩来进行这个游戏(所有人都要参加),女孩只会挑选她喜欢的男孩,并且她们认为她们朋友喜欢的男孩她们也是喜欢的(朋友的男朋友也是我的男朋友???),而且她们遵循朋友的朋友也是朋友的原则,问她们最多可以玩几轮游戏(每轮要选择的人不能和以前选择的相同)。

 

分析:朋友关系很明显可以使用并查集找出来每个女孩可以连接的男孩,因为要求的是最多能进行多少轮游戏,也就是在这x轮游戏中每个女孩换了x不同的男孩,每个男孩也换了x个不同的女孩,如果源点和女孩相连,汇点和男孩相连,那么流量一定是N*x,可以使用二分来查找最大的x。

下面是AC代码。

=========================================================================================================================

#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<vector>
using namespace std;

const int MAXN = 207;
const int oo = 1e9+7;

int G[MAXN][MAXN], Layer[MAXN], N, M;
int girl[MAXN*MAXN], boy[MAXN*MAXN], father[MAXN];
vector<int>love[MAXN];

int Find(int x)
{
    if(father[x] != x)
        father[x] = Find(father[x]);
    return father[x];
}
void InIt()
{
    for(int i=1; i<=N; i++)
    {
        father[i] = i;
        love[i].clear();
    }
}
void BuidGraph(int flow, int start, int End)
{
    memset(G, 0, sizeof(G));

    for(int i=1; i<=N; i++)
    {///源点和女孩相连,汇点和男孩相连,流量是flow
        G[start][i] = flow;
        G[i+N][End] = flow;

        int u = Find(i);///注意别用father[i]
        int len = love[u].size();

        for(int j=0; j<len; j++)
        {///女孩和男孩之间的流量是1
            G[i][love[u][j]] = 1;
        }
    }
}
bool BFS(int start, int End)
{
    memset(Layer, 0, sizeof(Layer));
    queue<int> Q;
    Q.push(start);
    Layer[start] = 1;

    while(Q.size())
    {
        int u = Q.front();Q.pop();

        if(u == End)return true;

        for(int v=1; v<=End; v++)
        {
            if(Layer[v]==false && G[u][v])
            {
                Layer[v] = Layer[u] + 1;
                Q.push(v);
            }
        }
    }

    return false;
}
int DFS(int u, int MaxFlow, int End)
{
    if(u == End)return MaxFlow;

    int uflow = 0;

    for(int v=1; v<=End; v++)
    {
        if(Layer[v]==Layer[u]+1 && G[u][v])
        {
            int flow = min(MaxFlow-uflow, G[u][v]);
            flow = DFS(v, flow, End);

            G[u][v] -= flow;
            G[v][u] += flow;
            uflow += flow;

            if(uflow == MaxFlow)
                break;
        }
    }

    if(uflow == 0)
        Layer[u] = 0;
    return uflow;
}
int Dinic(int start, int End)
{
    int MaxFlow = 0;

    while(BFS(start, End) == true)
        MaxFlow += DFS(start, oo, End);

    return MaxFlow;
}

int main()
{
    int T;

    scanf("%d", &T);

    while(T--)
    {
        int i, F, u, v;

        scanf("%d%d%d", &N, &M, &F);

        InIt();

        for(i=1; i<=M; i++)
            scanf("%d%d", &girl[i], &boy[i]);
        for(i=1; i<=F; i++)
        {///用并查集合并朋友关系
            scanf("%d%d", &u, &v);
            u = Find(u);
            v = Find(v);

            if(u != v)
                father[u] = v;
        }

        for(i=1; i<=M; i++)
        {///把相同的朋友的男朋友全部都连接到根节点上,男生的区间N~2*N
            u = Find(girl[i]);
            love[u].push_back(boy[i]+N);
        }

        int start=N*2+1, End = start+1;
        int left = 0, right = N, ans=0;

        while(left <= right)
        {
            int Mid = (left+right)>>1;

            BuidGraph(Mid, start, End);
            int MaxFlow = Dinic(start, End);

            if(MaxFlow == Mid*N)
            {
                left = Mid + 1;
                ans = Mid;
            }
            else
                right = Mid - 1;
        }

        printf("%d\n", ans);
    }

    return 0;
}
时间: 2024-08-05 10:57:09

N - Marriage Match II - HDU 3081(最大流)的相关文章

hdu 3081 hdu 3277 hdu 3416 Marriage Match II III IV //最大流的灵活运用

3081 题意: n个女孩选择没有与自己吵过架的男孩有连边(自己的朋友也算,并查集处理),2分图,有些边,求有几种完美匹配(每次匹配每个点都不重复匹配) 我是建二分图后,每次增广一单位,(一次完美匹配),再修改起点还有终点的边流量,继续增广,直到达不到完美匹配为止.网上很多是用二分做的,我觉得没必要...(网上传播跟风真严重...很多人都不是真正懂最大流算法的...) 3277 : 再附加一条件,每个女孩可以最多与k个自己不喜欢的男孩.求有几种完美匹配(同上). 我觉得:求出上题答案,直接ans

HDU 3081 Marriage Match II(二分+最大流)

HDU 3081 Marriage Match II 题目链接 题意:n个女孩n个男孩,每个女孩可以和一些男孩配对,然后有些女孩是朋友,满足这个朋友圈里面的人,如果有一个能和某个男孩配对,其他就都可以,然后每轮要求每个女孩匹配到一个男孩,且每轮匹配到的都不同,问最多能匹配几轮 思路:二分轮数k,然后建图为,源点连向女孩,男孩连向汇点容量都为k,然后女孩和男孩之间连边为,有关系的连边容量1,这样一个匹配对应一条边,且不会重复,每次判断最大流是否等于n * k即可 代码: #include <cst

hdu 3081 Marriage Match II (二分+最大流+并查集)

hdu 3081 Marriage Match II Description Presumably, you all have known the question of stable marriage match. A girl will choose a boy; it is similar as the game of playing house we used to play when we are kids. What a happy time as so many friends p

【HDU3081】Marriage Match II (二分+最大流)

Description Presumably, you all have known the question of stable marriage match. A girl will choose a boy; it is similar as the game of playing house we used to play when we are kids. What a happy time as so many friends playing together. And it is

HDU 3081 Marriage Match II(二分法+最大流量)

HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个女孩n个男孩,每一个女孩能够和一些男孩配对.然后有些女孩是朋友.满足这个朋友圈里面的人,假设有一个能和某个男孩配对,其它就都能够,然后每轮要求每一个女孩匹配到一个男孩.且每轮匹配到的都不同,问最多能匹配几轮 思路:二分轮数k,然后建图为,源点连向女孩,男孩连向汇点容量都为k,然后女孩和男孩之间连边为.有关系的

hdu 3081 Marriage Match II(最大流 + 二分 + 并查集)

Marriage Match II                                                                           Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Presumably, you all have known the question of stable

HDU 3081 Marriage Match II 二分+最大流

题目来源:HDU 3081 Marriage Match II 题意: 思路: 错误代码 纠结不知道哪错了 先放一放 #include <cstdio> #include <queue> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1010; const int INF = 999999999; st

HDU 3081 Marriage Match II

Marriage Match II Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 308164-bit integer IO format: %I64d      Java class name: Main Presumably, you all have known the question of stable marriage match. A girl wi

Marriage Match II (hdu 3081 二分图+并查集)

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2455    Accepted Submission(s): 837 Problem Description Presumably, you all have known the question of stable marriage match. A