題目描述:(二分圖最大匹配問題)
若兩個正整數的和爲素數,則這兩個正整數稱之爲“素數伴侶”,如2和5、6和13,它們能應用於通信加密。現在密碼學會請你設計一個程序,從已有的N(N爲偶數)個正整數中挑選出若干對組成“素數伴侶”,挑選方案多種多樣,例如有4個正整數:2,5,6,13,如果將5和6分爲一組中只能得到一組“素數伴侶”,而將2和5、6和13編組將得到兩組“素數伴侶”,能組成“素數伴侶”最多的方案稱爲“最佳方案”,當然密碼學會希望你尋找出“最佳方案”。
輸入描述:
有一個正偶數N(N≤100),表示待挑選的自然數的個數。後面給出N個具體的數字,範圍爲[2,30000]。
4 2 5 6 13
輸出描述:
求得的“最佳方案”組成“素數伴侶”的對數。
2
二分圖最大匹配問題:
1.問題引出
通過數代人的努力,你終於趕上了剩男剩女的大潮,假設你是一位光榮的新世紀媒人,在你的手上有N個剩男,M個剩女,每個人都可能對多名異性有好感。
如果一對男女互有好感,那麼你就可以把這一對撮合在一起,你擁有的大概就是下面這樣一張關係圖,每一條連線都表示互有好感。並且現在的要求是,儘可能撮合更多對新人。
2. 嘗試進行解決
find(x); //表示當前對x號男生進行尋偶 line[i][j]; //表示 i 號男生和 j 號女生是否有好感 girl[j]; //表示 j 號女生的配偶編號 used[]; //在當前挑選過程中,有哪些女生被宣佈了主權 line_num++; //x號男生牽手成功 僞代碼: used[] 爲全局變量,因爲發生遞歸時候要共用 girl[] 爲全局變量,因爲發生遞歸時候要共用 line[][] 爲全局變量,因爲發生遞歸時候要共用 for(int i=0; i<M; i++) //遍歷所有男生 { memset(used,0,sieof(used)); //處理i號男生時候0個女生被宣佈主權 } bool find(int x) { for(int j=0; j<N; j++) { if( line[x][j]==1&&used[j]==-1 ) //互有好感且女生沒有被宣佈主權 { used[j] = x; // x號男生對 j 號女生宣佈主權 if( gir[j]==-1 ) //如果名花無主 { girl[j] = x; // x號男生的配偶是 j 號女生 return true; //找到了就結束 }else{ // 名花有主的情況下,看能不能讓這個主騰一下位置 if( find(girl[j]) ){ girl[j] = x; // x號男生的配偶是 j 號女生 return true; //找到了就結束 } } } } return false; //表示x不能再找到新的女生 }
順序遍歷每個男生,假設當前是 1 號男生
①順序遍歷所有女生嘗試給1號男生找女朋友( find(1) ),此時1號男生沒有對任何一個女生宣佈主權( used[]={0} ),發現和一號女生互有好感 line(1,1)==true,宣佈自己對1號女生的主權 used[1]=true。發現1號女生無主( girl[1]==-1 )get,將1號女生配偶編號改變( girl[1]=1 ),對數加1(藍線)line_num++;
注意到:互有好感&&女生無主 纔可以get,line_num++
②順序遍歷所有女生嘗試給2號男生找女朋友 ( find(2) ),此時2號男生沒有對任何一個女生宣佈主權( used[]={0} ),發現和一號女生互有好感 line(2,1)==true,宣佈對1號女生的主權 used[1]=true。但是1號女生有主,無法get。
此時讓一號女生原來的男朋友即1號男生去尋找女朋友即( find(1) ),此時used中已經存在了一個被宣佈主權的( used[1]==1 )(注意此時1號男生的find是嵌套在2號男生的find內部(發生了遞歸),並且2號男生和1號男生公用一個used[],這個used是目前只有2號男生有一個宣佈主權的對象,這就保證了,1號男生不會選擇當前已經被宣佈了主權的)
我們來觀察find(1), 未完待續........