HDU 4687 Boke and Tsukkomi (一般图匹配带花树)

来源:互联网 发布:执行仪表板软件 编辑:程序博客网 时间:2024/06/10 21:37

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4687


题意:求出一般图的最大匹配数(匹配方案可能有多种),找出哪些边无法构成任一最大匹配方案


思路:先跑出最大匹配数tot,然后枚举每一条边,强制将这条边上的两端点匹配,然后再跑最大匹配,如果跑出的结果 < tot - 1,那这条边就不是构成最大匹配的边



#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <cmath>#include <queue>#include <utility>#include <functional>#include <string>#include <cctype>#include <list>using namespace std;const int MAXN = 300;int N, M; //点的个数,点的编号从1到Nbool Graph[MAXN][MAXN], g[MAXN][MAXN];int Match[MAXN];bool InQueue[MAXN], InPath[MAXN], InBlossom[MAXN];int Head, Tail;int Queue[MAXN];int Start, Finish;int NewBase;int Father[MAXN], Base[MAXN];int Count;//匹配数,匹配对数是Count/2pair <int, int> p[MAXN];void CreateGraph(){    memset(Graph, false, sizeof(Graph));    memset(g, false, sizeof(g));    for (int i = 1; i <= M; i++)    {        int u, v;        scanf("%d%d", &u, &v);        Graph[u][v] = Graph[v][u] = true;        g[u][v] = g[v][u] = true;        p[i].first = u, p[i].second = v;    }}void Push(int u){    Queue[Tail] = u;    Tail++;    InQueue[u] = true;}int Pop(){    int res = Queue[Head];    Head++;    return res;}int FindCommonAncestor(int u, int v){    memset(InPath, false, sizeof(InPath));    while (true)    {        u = Base[u];        InPath[u] = true;        if (u == Start) break;        u = Father[Match[u]];    }    while (true)    {        v = Base[v];        if (InPath[v])break;        v = Father[Match[v]];    }    return v;}void ResetTrace(int u){    int v;    while (Base[u] != NewBase)    {        v = Match[u];        InBlossom[Base[u]] = InBlossom[Base[v]] = true;        u = Father[v];        if (Base[u] != NewBase) Father[u] = v;    }}void BloosomContract(int u, int v){    NewBase = FindCommonAncestor(u, v);    memset(InBlossom, false, sizeof(InBlossom));    ResetTrace(u);    ResetTrace(v);    if (Base[u] != NewBase) Father[u] = v;    if (Base[v] != NewBase) Father[v] = u;    for (int tu = 1; tu <= N; tu++)        if (InBlossom[Base[tu]])        {            Base[tu] = NewBase;            if (!InQueue[tu]) Push(tu);        }}void FindAugmentingPath(){    memset(InQueue, false, sizeof(InQueue));    memset(Father, 0, sizeof(Father));    for (int i = 1; i <= N; i++)   Base[i] = i;    Head = Tail = 1;    Push(Start);    Finish = 0;    while (Head < Tail)    {        int u = Pop();        for (int v = 1; v <= N; v++)            if (Graph[u][v] && (Base[u] != Base[v]) && (Match[u] != v))            {                if ((v == Start) || ((Match[v] > 0) && Father[Match[v]] > 0))      BloosomContract(u, v);                else if (Father[v] == 0)                {                    Father[v] = u;                    if (Match[v] > 0)                        Push(Match[v]);                    else                    {                        Finish = v;                        return;                    }                }            }    }}void AugmentPath(){    int u, v, w;    u = Finish;    while (u > 0)    {        v = Father[u];        w = Match[v];        Match[v] = u;        Match[u] = v;        u = w;    }}void Edmonds(){    memset(Match, 0, sizeof(Match));    for (int u = 1; u <= N; u++)        if (Match[u] == 0)        {            Start = u;            FindAugmentingPath();            if (Finish > 0)                AugmentPath();        }}int PrintMatch(){    Edmonds();    Count = 0;    for (int u = 1; u <= N; u++)        if (Match[u] > 0)            Count++;    return Count / 2;}vector <int> pnt;int main(){    while (~scanf("%d%d", &N, &M))    {        pnt.clear();        CreateGraph();        int sum = PrintMatch();        for (int i = 1; i <= M; i++)        {            int u = p[i].first, v = p[i].second;            memcpy(Graph, g, sizeof(g));            for (int j = 1; j <= N; j++)                Graph[u][j] = Graph[j][u] = Graph[v][j] = Graph[j][v] = false;            int res = PrintMatch();            if (res < sum - 1)                pnt.push_back(i);        }        int cnt = pnt.size();        printf("%d\n", cnt);        for (int i = 0; i < cnt; i++)        {            if (i != cnt - 1)                printf("%d ", pnt[i]);            else                printf("%d", pnt[i]);        }        printf("\n");    }    return 0;}




0 0