一般图最大匹配--带花树

#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();
}

 

posted @ 2013-07-24 17:27  yefeng1627  阅读(869)  评论(0编辑  收藏  举报

Launch CodeCogs Equation Editor