一般图最大匹配--带花树
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const double esp = 1e-8; #define Fact(x) ((x)*(x)) //一般图匹配带花树 const int MaxN = 111; 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; void CreateGraph() { int u, v; memset(Graph,false,sizeof(Graph)); scanf("%d", &N); while( 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( 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 BlossomContract(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) ) ) BlossomContract(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] ); } struct Point{ int x, y; Point(){} Point(int _x,int _y):x(_x),y(_y){} Point operator - (const Point &b)const{ return Point(x-b.x,y-b.y); } int operator * (const Point &b)const{ return x*b.y-b.x*y; } double operator &(const Point &b)const{ return x*b.x+y*b.y; } }; struct Line{ Point s, e; double k; Line(){} Line(Point _s,Point _e){ s = _s; e = _e; } }; int sign(double x){ return x<-esp?-1:(x>esp);} double dist(Point a,Point b) { return sqrt( Fact(a.x-b.x) + Fact(a.y-b.y) ); } bool inter(Line l1, Line l2) { return max(l1.s.x,l1.e.x) >= min( l2.s.x,l2.e.x) && max(l2.s.x,l2.e.y) >= min( l1.s.x,l1.e.x) && max(l1.s.y,l1.e.y) >= min( l2.s.y,l2.e.y) && max(l2.s.y,l2.e.y) >= min( l1.s.y,l1.e.y) && sign( (l2.s-l1.s)*(l1.e-l1.s) )*sign( (l2.e-l1.s)*(l1.e-l1.s) ) <= 0 && sign( (l1.s-l2.s)*(l2.e-l2.s) )*sign( (l1.e-l2.s)*(l2.e-l2.s) ) <= 0; } void gao(){ CreateGraph(); Edmonds(); PrintMatch(); }