最大匹配,花樹開花算法

最初圖是用的數組線性表存的,但是TLE了,後來直接用矩陣存的然後就AC了,表面上看用矩陣存似乎花的時間多,因爲訪問了一些不存在的邊,但是用臨接矩陣存有重邊的情況就很不好,所以還是用矩陣吧!

class match{
public:
    queue<int>q;
    int n,m,len;
	int g[N][N];
    int pre[N];
    int next[N],base[N],fre[N];
    int inpath[N],inblossom[N],inque[N];

    void init()
    {
        len=1;
        memset(next,-1,sizeof(next));
		memset(g,false,sizeof(g));
    }
    void addpage(int s,int t)
    {
		g[s][t]=g[t][s]=true;
    }
    int findancestor(int x,int y)//xunzhao sousuo zhong zuixiao
        //de gongtong de zuxian
    {
        //panduan zaimeizai yitiao lushang
        memset(inpath,0,sizeof(inpath));
        while(true)
        {
            x=base[x];//zhengg suodian de 
            inpath[x]=true;
            if(next[x]==-1) break;
            x=fre[next[x]];
        }
        while(true)
        {
            y=base[y];
            if(inpath[y]) return y;
            y=fre[next[y]];//匹配dnage xiao de ba
        }
    }
    void reset(int x,int anc)  
    {
        while(x!=anc)
        {
            //inblossom jilu de shi base de zhi de 
            int y=next[x];
            inblossom[base[x]]=1;
            inblossom[base[y]]=1;
            y=fre[y];
            if(base[y]!=anc) fre[y]=next[x];
            x=y;
        }
    }
    void contract(int x,int y)
    {
        int anc=findancestor(x,y);
        memset(inblossom,0,sizeof(inblossom));
        reset(x,anc);
        reset(y,anc);
        if(base[x]!=anc) fre[x]=y;
        if(base[y]!=anc) fre[y]=x;
        rep(i,n)//suodian bing jiaru duilie de 
            if(inblossom[base[i]])
            {
                base[i]=anc;
                if(!inque[i])
                {
                    q.push(i);
                    inque[i]=1;
                }
            }
    }
    bool dfs(int s)
    {
       memset(fre,-1,sizeof(fre));//jilu zai shuzhong de zuihouyige jiedian
       memset(inque,0,sizeof(inque));
       rep(i,n) base[i]=i;//yonglai biaoji hua de 
       while(!q.empty()) q.pop();
       q.push(s);
       inque[s]=1;
       while(!q.empty())
       {
           int x=q.front(); q.pop();
           rep(y,n)
           {
               if(g[x][y]==false) continue;
               // zai yige hua nei jiu mei yisi le
               //zai yige shu nei zaiqu sousuo ye jiu mei yisi le
               if(base[x]!=base[y] && next[x]!=y)
               {
                   if(y==s ||( next[y]!=-1 && fre[next[y]]!=-1))
                       contract(x,y);
                   else if(fre[y]==-1)//y meiyou zai shushang
                   {
                       fre[y]=x;
                       if(next[y]!=-1)
                           q.push(next[y]),inque[next[y]]=1;
                       else
                       {
                           x=y;//success
                           while(x!=-1)
                           {// backtrick
                               //dfs point
                               y=fre[x];//record preview
                               int w=next[y];
                               next[x]=y;
                               next[y]=x;
                               x=w;
                           }
                           return true;
                       }
                   }
               }
           }
       }
       return false;
    }
    int work()
    {
        int ans=0;
        rep(i,n)
        {
            if(next[i]!=-1) continue;
            if(dfs(i))//meiyou pipei de 
                ++ans;
        }
        return ans;
    }

};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章