比賽的時候剛開始看這題還以為是二分圖匹配,後來才發現根本不是,因為該題存在長度為奇數的圈 。 比如1->2,2->3,3->1 。 所以該題要用一般圖匹配,即帶花樹算法 。
比賽時抄的模板有地方抄錯了,上述樣例出現了死循環 。 賽後補題的時候用map去重卻得不到正確答案,不知為何,暫放 ,下面給出一種正確解法。
細節參見代碼:
#include #include #include #include #include #include #include #include #include #include using namespace std; const int maxn = 55; int n,m,Match[maxn],Head,Tail,Queue[maxn],Start,Finish,NewBase,Father[maxn],Base[maxn],cnt,Count; bool InQueue[maxn],InPath[maxn],InBlossom[maxn],Graph[maxn][maxn]; 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 getMatch() { Edmonds(); Count = 0; for(int u = 1; u <= n; u++) if(Match[u] > 0) Count++; return Count/2; } struct node { int a,b; node(int a=0,int b=0): a(a),b(b) {} bool operator < (const node& rhs) const { return a < rhs.a || (a == rhs.a && b < rhs.b); } bool operator == (const node& rhs)const { return a == rhs.a && b == rhs.b; } } e[155],ee[155]; map p; void PrintMatch() { cnt = getMatch(); vector ans; int g[maxn][maxn]; memcpy(g,Graph,sizeof(g)); for(int i=0;i
1.The C++ Programming L
在C++中,動態內存的管理是通過一對運算符來完成的:new,
背景使用Dubbo的時候發現當Zookeeper、Dubbo
Is It A Tree? Time Limi
題意: n個雷,分別在a[1]...a[n] ,走一步概率為
#include using namespace std ;