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

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

}

 

你可能感兴趣的:(匹配)