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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tony5t4rk/article/details/81981870

文章地址:http://henuly.top/?p=797

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 normal that a fight or a quarrel breaks out, but we will still play together after that, because we are kids.
Now, there are 2n kids, n boys numbered from 1 to n, and n girls numbered from 1 to n. you know, ladies first. So, every girl can choose a boy first, with whom she has not quarreled, to make up a family. Besides, the girl X can also choose boy Z to be her boyfriend when her friend, girl Y has not quarreled with him. Furthermore, the friendship is mutual, which means a and c are friends provided that a and b are friends and b and c are friend.
Once every girl finds their boyfriends they will start a new round of this game—marriage match. At the end of each round, every girl will start to find a new boyfriend, who she has not chosen before. So the game goes on and on.
Now, here is the question for you, how many rounds can these 2n kids totally play this game?

Input:

There are several test cases. First is a integer T, means the number of test cases.
Each test case starts with three integer n, m and f in a line (3<=n<=100,0

Output:

For each case, output a number in one line. The maximal number of Marriage Match the children can play.

Sample Input:

1
4 5 2
1 1
2 3
3 2
4 2
4 4
1 4
2 3

Sample Output:

2

题目链接

N个女生和N个男生进行匹配,每个女生有其对应有好感的男生,若两个女生是好朋友的话他们那么对对方有好感的男生也有好感,每轮匹配女生选择的男生不能出现重复,求最多可以进行多少轮匹配。

存储女生和男生的关系网,在读取女生之间关系数据时对女生利用并查集进行合并,之后根据并查集完善女生和男生的关系网,然后二分答案,利用二分的答案进行建图跑最大流。

建图时把源点与女生相连,流量为二分值,再把男生与汇点相连,流量也为二分值,之后利用男生与女生的关系网在有好感的男生女生之间建立一条流量为1的边,根据最大流结果与二分值*N的关系更新二分边界。

若当前二分值可以满足匹配轮数的话源点和汇点所连接的所有边全部满流,最大流结果就是二分值*N,当前二分值还可以再增大,若不满足则最大流结果不等于二分值*N,缩小二分右边界(二分值)。

AC代码:

#include <bits/stdc++.h>
const int INF = 0x3f3f3f3f;
const int maxn = 2e2 + 5;

struct Link {
    int V, Weight, Next;
    Link(int _V = 0, int _Weight = 0, int _Next = 0): V(_V), Weight(_Weight), Next(_Next) {}
};

Link edges[maxn * maxn * 2];
int Head[maxn * maxn * 2];
int Tot;
int Depth[maxn * maxn * 2];
int Current[maxn * maxn * 2];

int Pre[maxn];

int TCase;
int N, M, F;
bool Relation[maxn][maxn];

void Init() {
    Tot = 0;
    memset(Head, -1, sizeof(Head));
}

void AddEdge(int U, int V, int Weight, int ReverseWeight = 0) {
    edges[Tot].V = V;
    edges[Tot].Weight = Weight;
    edges[Tot].Next = Head[U];
    Head[U] = Tot++;
    edges[Tot].V = U;
    edges[Tot].Weight = ReverseWeight;
    edges[Tot].Next = Head[V];
    Head[V] = Tot++;
}

bool Bfs(int Start, int End) {
    memset(Depth, -1, sizeof(Depth));
    std::queue<int> Que;
    Depth[Start] = 0;
    Que.push(Start);
    while (!Que.empty()) {
        int Vertex = Que.front();
        Que.pop();
        for (int i = Head[Vertex]; i != -1; i = edges[i].Next) {
            if (Depth[edges[i].V] == -1 && edges[i].Weight > 0) {
                Depth[edges[i].V] = Depth[Vertex] + 1;
                Que.push(edges[i].V);
            }
        }
    }
    return Depth[End] != -1;
}

int Dfs(int Vertex, int End, int NowFlow) {
    if (Vertex == End || NowFlow == 0) {
        return NowFlow;
    }
    int UsableFlow = 0, FindFlow;
    for (int &i = Current[Vertex]; i != -1; i = edges[i].Next) {
        if (edges[i].Weight > 0 && Depth[edges[i].V] == Depth[Vertex] + 1) {
            FindFlow = Dfs(edges[i].V, End, std::min(NowFlow - UsableFlow, edges[i].Weight));
            if (FindFlow > 0) {
                edges[i].Weight -= FindFlow;
                edges[i ^ 1].Weight += FindFlow;
                UsableFlow += FindFlow;
                if (UsableFlow == NowFlow) {
                    return NowFlow;
                }
            }
        }
    }
    if (!UsableFlow) {
        Depth[Vertex] = -2;
    }
    return UsableFlow;
}

int Dinic(int Start, int End) {
    int MaxFlow = 0;
    while (Bfs(Start, End)) {
        for (int i = 0; i <= N + N + 1; ++i) {
            Current[i] = Head[i];
        }
        MaxFlow += Dfs(Start, End, INF);
    }
    return MaxFlow;
}

int Find(int X) {
    int R = X;
    while (Pre[R] != R) {
        R = Pre[R];
    }
    return R;
}

void Join(int X, int Y) {
    int XX = Find(X);
    int YY = Find(Y);
    if (XX != YY) {
        Pre[XX] = YY;
    }
}

int main(int argc, char *argv[]) {
    scanf("%d", &TCase);
    for (int Case = 1; Case <= TCase; ++Case) {
        memset(Relation, false, sizeof(Relation));
        scanf("%d%d%d", &N, &M, &F);
        for (int i = 1; i <= N; ++i) {
            Pre[i] = i;
        }
        for (int i = 1, A, B; i <= M; ++i) {
            scanf("%d%d", &A, &B);
            Relation[A][N + B] = true;
        }
        for (int i = 1, C, D; i <= F; ++i) {
            scanf("%d%d", &C, &D);
            Join(C, D);
        }
        for (int i = 1; i <= N; ++i) {
            for (int j = i + 1; j <= N; ++j) {
                if (Find(i) == Find(j)) {
                    for (int k = N + 1; k <= N + N; ++k) {
                        Relation[i][k] = Relation[j][k] = (Relation[i][k] || Relation[j][k]);
                    }
                }
            }
        }
        int Left = 0, Right = 1e5;
        while (Left < Right) {
            int Mid = Left + (Right - Left + 1) / 2;
            Init();
            for (int i = 1; i <= N; ++i) {
                AddEdge(0, i, Mid);
                for (int j = N + 1; j <= N + N; ++j) {
                    if (i == 1) {
                        AddEdge(j, N + N + 1, Mid);
                    }
                    if (Relation[i][j]) {
                        AddEdge(i, j, 1);
                    }
                }
            }
            if (N * Mid == Dinic(0, N + N + 1)) {
                Left = Mid;
            }
            else {
                Right = Mid - 1;
            }
        }
        printf("%d\n", Left);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Tony5t4rk/article/details/81981870