HDUOJ 4687 Boke and Tsukkomi

HDUOJ 4687 Boke and Tsukkomi

题目链接

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

一般图最大匹配~
题目要求多余的边,考虑割边即可,先求出原图的最大匹配数 n u m num ,若割边后求处的最大匹配数不满足 c n t ! = n u m 1 cnt!=num-1 ,则说明这条边是多余的,AC代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N=150;
deque<int>q;
vector<int>ans;
bool g[N][N],inque[N],inblossom[N],vis[N];
int match[N],pre[N],base[N];
int n,m,a,b;

struct node{
    int u,v;
}e[N];
int Find(int u,int v){
    bool inpath[N]={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=Find(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(g[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 calculate()
{
    int ans=0;
    memset(match,-1,sizeof(match));
    for(int i=1;i<=n;i++)
        if(match[i]==-1&&dfs(i,n)) ans++;
    return ans;
}

int main()
{
    while(~scanf("%d%d",&n,&m)){
        memset(g,false,sizeof(g));
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            g[a][b]=g[b][a]=true;
            e[i].u=a;e[i].v=b;
        }
        ans.clear();
        int res=calculate();
        for(int i=1;i<=m;i++){
            a=e[i].u,b=e[i].v;
            memset(g,false,sizeof(g));
            for(int j=1;j<=m;j++){
                if(i!=j){
                    int x=e[j].u,y=e[j].v;
                    if(x==a||x==b||y==a||y==b) continue;
                    g[x][y]=g[y][x]=true;
                }
            }
            int t=calculate();
            if(t!=res-1) ans.push_back(i);
        }
        printf("%d\n",ans.size());
        for(int i=0;i<ans.size();i++)
            i==0?printf("%d",ans[i]):printf(" %d",ans[i]);
        puts("");
    }
    return 0;
}
发布了479 篇原创文章 · 获赞 38 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qq_43765333/article/details/105711889