HDU4687-Boke and Tsukkomi(一般图匹配带花树)

来源:互联网 发布:java 3d引擎 编辑:程序博客网 时间:2024/05/24 23:14

Boke and Tsukkomi

                                                                      Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
                                                                                                 Total Submission(s): 1094    Accepted Submission(s): 350


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 41 32 32 43 16 61 23 23 45 25 45 6
 

Sample Output
1232 4 5
 

Author
Zejun Wu (watashi)
 

Source
2013 Multi-University Training Contest 9
 

题意:有n个女孩,她们之间有k对可能的组合,但参赛时每个人只能参加一个组合,在组合数量最大化时有些组合是多余的,但使组合数量最大化可能有多种方式,找出这些多余的组合

解题思路:一般图匹配带花树,这题不能这样判断,当一个组合不选择时,组合数量仍能达到最大化,它就是多余组合,因为可能选了这个组合也能使组合数量达到最大化。应该固定一个组合,若其他组合形成的组合数量等于之前组合数量减一,那么它就不是多余的,否则它就是多余的。也就是说要让剩余的组合无论怎么选都能达到组合数量最大化


#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <algorithm>#include <queue>#include <vector>#include <set>#include <stack>#include <map>#include <climits>#include <functional>#include <bitset>using namespace std;#define LL long longconst int INF=0x3f3f3f3f;const int MAXN=50;int n,m;//点的个数,点的编号从1到Nbool g[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;//匹配数,匹配对数是Count/2struct node{    int x,y;} p[150];void Push(int u){    Queue[tail]=u;    tail++;    inqueue[u]=true;}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 BloosomContract(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=Queue[head];        head++;        for(int v=1; v<=n; v++)        {            if(g[u][v]&&(base[u]!=base[v])&&(match[u]!=v))            {                if((v==start)||((match[v]>0)&&Father[match[v]]>0))                    BloosomContract(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();        }    }}int main(){    int ans[150];    while(~scanf("%d %d",&n,&m))    {        memset(g,false,sizeof(g));        for(int i=1; i<=m; i++)        {            scanf("%d %d",&p[i].x,&p[i].y);            g[p[i].x][p[i].y]=g[p[i].y][p[i].x]=true;        }        Edmonds();//进行匹配        Count=0;        for(int i=1; i<=n; i++)            if(match[i]>0) Count++;        Count/=2;        int cnt=0;        for(int i=1; i<=m; i++)        {            int u=p[i].x,v=p[i].y;            memset(g,false,sizeof(g));            for(int j=1; j<=m; j++)            {                if(u==p[j].x||v==p[j].x||u==p[j].y||v==p[j].y) continue;                g[p[j].x][p[j].y]=g[p[j].y][p[j].x]=true;            }            Edmonds();//进行匹配            int sum=0;            for(int j=1; j<=n; j++)                if(match[j]>0) sum++;            sum/=2;            if(sum!=Count-1) ans[cnt++]=i;        }        printf("%d\n",cnt);        for(int i=0;i<cnt;i++)        {            printf("%d",ans[i]);            if(i<cnt-1) printf(" ");        }        printf("\n");    }    return 0;}

0 0
原创粉丝点击