1. 程式人生 > >[luogu2319 HNOI2006] 超級英雄 (匈牙利算法)

[luogu2319 HNOI2006] 超級英雄 (匈牙利算法)

sdi 不同的 tor 輸出 是我 desc new eof vector

傳送門

Description

現在電視臺有一種節目叫做超級英雄,大概的流程就是每位選手到臺上回答主持人的幾個問題,然後根據回答問題的多少獲得不同數目的獎品或獎金。主持人問題準備了若幹道題目,只有當選手正確回答一道題後,才能進入下一題,否則就被淘汰。為了增加節目的趣味性並適當降低難度,主持人總提供給選手幾個“錦囊妙計”,比如求助現場觀眾,或者去掉若幹個錯誤答案(選擇題)等等。

這裏,我們把規則稍微改變一下。假設主持人總共有m道題,選手有n種不同的“錦囊妙計”。主持人規定,每道題都可以從兩種“錦囊妙計”中選擇一種,而每種“錦囊妙計”只能用一次。我們又假設一道題使用了它允許的錦囊妙計後,就一定能正確回答,順利進入下一題。現在我來到了節目現場,可是我實在是太笨了,以至於一道題也不會做,每道題只好借助使用“錦囊妙計”來通過。如果我事先就知道了每道題能夠使用哪兩種“錦囊妙計”,那麽你能告訴我怎樣選擇才能通過最多的題數嗎?

Input

輸入的第一行是兩個正整數 n 和 m ( 0 < n < 1001, 0 < m < 1001 )表示總共有 n 種“錦囊妙計”,編號為 0~n?1 ,總共有 m 個問題。

以下的m行,每行兩個數,分別表示第 m 個問題可以使用的“錦囊妙計”的編號。

註意,每種編號的“錦囊妙計”只能使用一次,同一個問題的兩個“錦囊妙計”可能一樣。

Output

輸出的第一行為最多能通過的題數 p ,接下來 p 行,每行為一個整數,第 i 行表示第 i 題使用的“錦囊妙計的編號”。

如果有多種答案,那麽任意輸出一種,本題使用 Special Judge 評判答案。

Sample Input

5 6
3 2
2 0
0 3
0 4
3 2
3 2

Sample Output

4
3
2
0
4

Solution

裸匈牙利算法

Code

//By Menteur_Hxy
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;

int read() {
    int x=0,f=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f; c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=1010;
int n,m,ans;
int vis[N],l[N],r[N];
vector<int> V[N];

bool dfs(int u) {
    int siz=V[u].size(),v;
    F(i,0,siz-1) if(!vis[v=V[u][i]]) {
        vis[v]=1;
        if(!l[v]||dfs(l[v])) {
            l[v]=u;r[u]=v;
            return 1;
        }
    }
    return 0;
}

int main() {
    n=read(),m=read();
    F(i,1,m) {int x=read(),y=read();V[i].push_back(x),V[i].push_back(y);}
    F(i,1,m) {
        memset(vis,0,sizeof(vis));
        if(!dfs(i)) break;
        ans++;
    }
    printf("%d\n",ans);
    F(i,1,ans) printf("%d\n",r[i]);
    return 0;
}

[luogu2319 HNOI2006] 超級英雄 (匈牙利算法)