HDU 4687 Boke and Tsukkomi【带花树】

来源:互联网 发布:琉璃神社新域名 2017 编辑:程序博客网 时间:2024/05/29 13:59

题目链接

题意:一般图最大匹配后会有冗余的小组,求出这些冗余的小组。

明白题意后思路其实非常简单,先求一遍一般图最大匹配,然后枚举每个小组,如果这个小组冗余的话,去掉这个小组之后剩下的小组应该少于原来的减一。

一般图最大匹配就是传说中的带花树开花算法,看了遍解释没看懂……不过模板很容易套。

带花树开花算法

刚开始套了书上的模板TLE了,无奈之下又抄了一遍kuangbin的模板就过了……

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int maxn = 50;int n;bool Graph[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/2// void CreateGraph()// {// int u, v;// memset(Graph, false, sizeof(Graph));// scanf("%d", &N);// while (scanf("%d %d"), &u, &v != EOF)// Graph[u][v] = Graph[v][u] = true;// }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 (1){u = Base[u];InPath[u] = true;if (u == Start)break;u = Father[Match[u]];}while (1){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();}}void PrintMatch(){Count = 0;for (int u = 1; u <= n; u++)if (Match[u] > 0)Count++;printf("%d\n", Count);for (int u = 1; u <= n; u++)if (u < Match[u])printf("%d %d\n", u, Match[u]);}int GetMatch(){Edmonds();Count = 0;for (int u = 1; u <= n; u++)if (Match[u] > 0)Count++;return Count / 2;}int m;bool e[maxn][maxn];int cc;struct Edge{int xx, yy;} edge[150];int main(){while (scanf("%d %d", &n, &m) != EOF){memset(Graph, false, sizeof(Graph));memset(e, false, sizeof(e));for (int i = 1; i <= m; i++){int xx, yy;scanf("%d %d", &xx, &yy);edge[i].xx = xx;edge[i].yy = yy;Graph[xx][yy] = Graph[yy][xx] = true;e[xx][yy] = e[yy][xx] = true;}cc = GetMatch();vector <int> res;for (int i = 1; i <= m; i++){memcpy(Graph, e, sizeof(e));int u = edge[i].xx;int v = edge[i].yy;for (int j = 1; j <= n; j++){Graph[u][j] = Graph[j][u] = false;Graph[v][j] = Graph[j][v] = false;}int tmp = GetMatch();if (tmp < cc - 1)res.push_back(i);}printf("%d\n", res.size());for (int i = 0; i < res.size(); i++){if (i == 0)printf("%d", res[i]);elseprintf(" %d", res[i]);}putchar('\n');}return 0;}


原创粉丝点击