1. 程式人生 > >bzoj 1191超級英雄Hero|匈牙利演算法|水題

bzoj 1191超級英雄Hero|匈牙利演算法|水題

Description

現在電視臺有一種節目叫做超級英雄,大概的流程就是每位選手到臺上回答主持人的幾個問題,然後根據回答問題的多少獲得不同數目的獎品或獎金。主持人問題準備了若干道題目,只有當選手正確回答一道題後,才能進入下一題,否則就被淘汰。為了增加節目的趣味性並適當降低難度,主持人總提供給選手幾個“錦囊妙計”,比如求助現場觀眾,或者去掉若干個錯誤答案(選擇題)等等。 這裡,我們把規則稍微改變一下。假設主持人總共有m道題,選手有n種不同的“錦囊妙計”。主持人規定,每道題都可以從兩種“錦囊妙計”中選擇一種,而每種“錦囊妙計”只能用一次。我們又假設一道題使用了它允許的錦囊妙計後,就一定能正確回答,順利進入下一題。現在我來到了節目現場,可是我實在是太笨了,以至於一道題也不會做,每道題只好藉助使用“錦囊妙計”來通過。如果我事先就知道了每道題能夠使用哪兩種“錦囊妙計”,那麼你能告訴我怎樣選擇才能通過最多的題數嗎?

Input

輸入檔案的一行是兩個正整數n和m(0 < n <1001,0 < m < 1001)表示總共有n中“錦囊妙計”,編號為0~n-1,總共有m個問題。
以下的m行,每行兩個數,分別表示第m個問題可以使用的“錦囊妙計”的編號。
注意,每種編號的“錦囊妙計”只能使用一次,同一個問題的兩個“錦囊妙計”可能一樣。

Output

第一行為最多能通過的題數p

Sample Input

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

Sample Output

4

Hint

Source

HNOI2006

題解

裸的二分圖匹配……然而本蒟看混m和n依然WA了兩次而且還以為演算法寫錯了……
匈牙利演算法

程式碼

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1005;
struct data{int to,next;}e[maxn*2];
int head[maxn],cnt,qua[maxn],n,m;
bool used[maxn];
inline void insert(int u,int v){cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}
bool
dfs(int s) { for(int i=head[s];i;i=e[i].next) if(!used[e[i].to]) { used[e[i].to]=1; if(!qua[e[i].to]||dfs(qua[e[i].to])) { qua[e[i].to]=s; return 1; } } return 0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); if(x==y)insert(i,x); else insert(i,x),insert(i,y); } int ans=0; for(int i=1;i<=m;i++) { memset(used,0,sizeof(used)); if(dfs(i))ans++; else break; } printf("%d\n",ans); return 0; }

——既然選擇了遠方,便只顧風雨兼程