码迷,mamicode.com
首页 > 其他好文 > 详细

一般图匹配带花树

时间:2015-02-04 18:43:40      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:

二分图的匹配多采用匈牙利算法,而一般图的匹配则是带花树。

Problem Description
A new season of Touhou M-1 Grand Prix is approaching. Girls in Gensokyo cannot wait for participating it. Before the registration, they have to decide which combination they are going to compete as. Every girl in Gensokyo is both a boke (funny girl) and a tsukkomi (straight girl). Every candidate combination is made up of two girls, a boke and a tsukkomi. A girl may belong to zero or more candidate combinations, but one can only register as a member of one formal combination. The host of Touhou M-1 Grand Prix hopes that as many formal combinations as possible can participate in this year. Under these constraints, some candidate combinations are actually redundant as it\‘s impossible to register it as a formal one as long as the number of formal combinations has to be maximized. So they want to figure out these redundant combinations and stop considering about them.
技术分享
 

Input
There are multiple test cases. Process to the End of File.
The first line of each test case contains two integers: 1 ≤ N ≤ 40 and 1 ≤ M ≤ 123, where N is the number of girls in Gensokyo, and M is the number of candidate combinations. The following M lines are M candidate combinations, one by each line. Each combination is represented by two integers, the index of the boke girl 1 ≤ Bi ≤ N and the index of the tsukkomi girl 1 ≤ Ti ≤ N, where Bi != Ti.
 

Output
For each test case, output the number of redundant combinations in the first line. Then output the space-separated indexes of the redundant combinations in ascending order in the second line.
 

Sample Input
4 4 1 3 2 3 2 4 3 1 6 6 1 2 3 2 3 4 5 2 5 4 5 6
 

Sample Output
1 2 3 2 4 5
 

Author
Zejun Wu (watashi)
 

做法:构建无向图,一般图带花匹配,判断是否影响最大匹配。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
typedef long long LL;
typedef pair<int,int>pil;
pil temp[250];
int ans[50];
deque<int>Q;
const int MAXN=110;
bool mp[MAXN][MAXN],inque[MAXN],inblossom[MAXN],G[MAXN][MAXN];
int match[MAXN],pre[MAXN],base[MAXN];
int findancestor(int u,int v)
{
    bool inpath[MAXN]={false};
    while(1)
    {
        u=base[u];
        inpath[u]=true;
        if(match[u]==-1)break;
        u=pre[match[u]];
    }
    while(1)
    {
        v=base[v];
        if(inpath[v])return v;
        v=pre[match[v]];
    }
}
void reset(int u,int anc){
    while(u!=anc)
    {
        int v=match[u];
        inblossom[base[u]]=1;
        inblossom[base[v]]=1;
        v=pre[v];
        if(base[v]!=anc)pre[v]=match[u];
        u=v;
    }
}
void contract(int u,int v,int n){
    int anc=findancestor(u,v);
    memset(inblossom,0,sizeof(inblossom));
    reset(u,anc);reset(v,anc);
    if(base[u]!=anc)pre[u]=v;
    if(base[v]!=anc)pre[v]=u;
    for(int i=1;i<=n;i++)
        if(inblossom[base[i]])
        {
            base[i]=anc;
            if(!inque[i])
            {
                Q.push_back(i);
                inque[i]=1;
            }
        }
}

bool dfs(int S,int n){
    for(int i=0;i<=n;i++)pre[i]=-1,inque[i]=0,base[i]=i;
    Q.clear();Q.push_back(S);inque[S]=1;
    while(!Q.empty())
    {
        int u=Q.front();Q.pop_front();
        for(int v=1;v<=n;v++)
        {
            if(mp[u][v]&&base[v]!=base[u]&&match[u]!=v)
            {
                if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
                else if(pre[v]==-1)
                {
                    pre[v]=u;
                    if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
                    else
                    {
                        u=v;
                        while(u!=-1)
                        {
                            v=pre[u];
                            int w=match[v];
                            match[u]=v;
                            match[v]=u;
                            u=w;
                        }
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
int solve(int n)
{
    CLEAR(match,-1);
    int sum=0;
    for(int i=1;i<=n;i++)
        if(match[i]==-1&&dfs(i,n))
            sum++;
    return sum;
}
int main()
{
    int n,m;
    int x,y;
    while(~scanf("%d%d",&n,&m))
    {
        CLEAR(mp,0);
        REPF(i,1,m)
        {
            scanf("%d%d",&x,&y);
            temp[i].first=x;
            temp[i].second=y;
            mp[x][y]=mp[y][x]=1;
        }
        memcpy(G,mp,sizeof(mp));
        int s=solve(n);
        int k=0;
        REPF(l,1,m)
        {
            int u=temp[l].first;
            int v=temp[l].second;
            memcpy(mp,G,sizeof(G));
            REPF(i,1,n)
            {
                if(mp[u][i])
                    mp[u][i]=mp[i][u]=0;
                if(mp[v][i])
                    mp[v][i]=mp[i][v]=0;
            }
            if(solve(n)+1<s)
                ans[k++]=l;

        }
        printf("%d\n",k);
        if(k==0)  puts("");
        sort(ans,ans+k);
        for(int i=0;i<k;i++)
        {
            if(i!=k-1)  printf("%d ",ans[i]);
            else  printf("%d\n",ans[k-1]);
        }
    }
    return 0;
}

URAL 1099:

1099. Work Scheduling

Time limit: 0.5 second
Memory limit: 64 MB
There is certain amount of night guards that are available to protect the local junkyard from possible junk robberies. These guards need to scheduled in pairs, so that each pair guards at different night. The junkyard CEO ordered you to write a program which given the guards characteristics determines the maximum amount of scheduled guards (the rest will be fired). Please note that each guard can be scheduled with only one of his colleagues and no guard can work alone.

Input

The first line of the input contains one number N ≤ 222 which is the amount of night guards. Unlimited number of lines consisting of unordered pairs (ij) follow, each such pair means that guard #i and guard #j can work together, because it is possible to find uniforms that suit both of them (The junkyard uses different parts of uniforms for different guards i.e. helmets, pants, jackets. It is impossible to put small helmet on a guard with a big head or big shoes on guard with small feet). The input ends with Eof.

Output

You should output one possible optimal assignment. On the first line of the output write the even number C, the amount of scheduled guards. Then output C/2 lines, each containing 2 integers (ij) that denote that i and j will work together.

Sample

input output
3
1 2
2 3
1 3
2
1 2

直接输出匹配:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
typedef long long LL;
typedef pair<int,int>pil;
deque<int>Q;
const int MAXN=250;
bool mp[MAXN][MAXN],inque[MAXN],inblossom[MAXN],G[MAXN][MAXN];
int match[MAXN],pre[MAXN],base[MAXN];
int findancestor(int u,int v)
{
    bool inpath[MAXN]={false};
    while(1)
    {
        u=base[u];
        inpath[u]=true;
        if(match[u]==-1)break;
        u=pre[match[u]];
    }
    while(1)
    {
        v=base[v];
        if(inpath[v])return v;
        v=pre[match[v]];
    }
}
void reset(int u,int anc){
    while(u!=anc)
    {
        int v=match[u];
        inblossom[base[u]]=1;
        inblossom[base[v]]=1;
        v=pre[v];
        if(base[v]!=anc)pre[v]=match[u];
        u=v;
    }
}
void contract(int u,int v,int n){
    int anc=findancestor(u,v);
    memset(inblossom,0,sizeof(inblossom));
    reset(u,anc);reset(v,anc);
    if(base[u]!=anc)pre[u]=v;
    if(base[v]!=anc)pre[v]=u;
    for(int i=1;i<=n;i++)
        if(inblossom[base[i]])
        {
            base[i]=anc;
            if(!inque[i])
            {
                Q.push_back(i);
                inque[i]=1;
            }
        }
}

bool dfs(int S,int n){
    for(int i=0;i<=n;i++)pre[i]=-1,inque[i]=0,base[i]=i;
    Q.clear();Q.push_back(S);inque[S]=1;
    while(!Q.empty())
    {
        int u=Q.front();Q.pop_front();
        for(int v=1;v<=n;v++)
        {
            if(mp[u][v]&&base[v]!=base[u]&&match[u]!=v)
            {
                if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
                else if(pre[v]==-1)
                {
                    pre[v]=u;
                    if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
                    else
                    {
                        u=v;
                        while(u!=-1)
                        {
                            v=pre[u];
                            int w=match[v];
                            match[u]=v;
                            match[v]=u;
                            u=w;
                        }
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
int solve(int n)
{
    CLEAR(match,-1);
    int sum=0;
    for(int i=1;i<=n;i++)
        if(match[i]==-1&&dfs(i,n))
            sum++;
    return sum;
}
int main()
{
    int n;
    int x,y;
    while(~scanf("%d",&n))
    {
        CLEAR(mp,0);
        while(~scanf("%d%d",&x,&y))
            mp[x][y]=mp[y][x]=1;
        int s=solve(n);
        printf("%d\n",s*2);
        REPF(i,1,n)
        {
            for(int j=i+1;j<=n;j++)
                if(match[j]==i)
                  printf("%d %d\n",i,j);
        }
    }
    return 0;
}


一般图匹配带花树

标签:

原文地址:http://blog.csdn.net/u013582254/article/details/43488975

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!