<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          算法:單身男女問題的科學(xué)解決方案

          共 4520字,需瀏覽 10分鐘

           ·

          2021-03-04 10:15

          點(diǎn)擊上方藍(lán)字 關(guān)注我,漲知識


          以下場景太過真實(shí),但都是虛構(gòu),為了講清楚理論的過程。如有雷同,純屬我瞎編,還望勿對號入座。

          01
          婚戀市場,明碼實(shí)價(jià)
          中國如今男女比例嚴(yán)重失衡,2021年預(yù)計(jì)將有9200萬單身貴族。為了幫助解決這個(gè)社會(huì)性問題,提升整體人民的幸福感,小K打算投身到這份偉大的事業(yè)中。
          幾何思維”婚戀所,用最科學(xué)的方法,幫你脫單。通過概率論尋找最佳匹配對象,再通過微積分精確計(jì)算好感上升曲線,最后用數(shù)值分析無限逼近對方的理想型。最可怕的是,還包郵呢親,關(guān)注一波了解一下?
          上班第一天,老板給了小K一份單身男女好感的數(shù)據(jù)資料。如下圖,連線表示雙方互有好感,可以嘗試處對象。突然有一個(gè)問題,怎樣才能找出最大匹配呢?


          02
          不要慫,就是干
          很多時(shí)候不是你比別人差,而是你執(zhí)行力不夠,在猶豫中喪失機(jī)會(huì)。
          大家就先行動(dòng)起來吧。
          快看,男1號選手在小K的鼓勵(lì)(慫恿)下,率先對女1號發(fā)起了進(jìn)攻。在離失敗只有0.01公分的時(shí)候,他竟然奇跡般的完成反殺,沒錯(cuò),他成功啦,這種高超的技巧,嫻熟的手法簡直如同教科書一般,值得在座的每個(gè)同學(xué)深入研究反復(fù)琢磨啊。
          男2號選手也不甘落后,也對女2號選手發(fā)起了進(jìn)攻,沒錯(cuò),又一次成功啦。
          男3號選手:我勒個(gè)去,我上我也行啊。于是也對自己心動(dòng)的女1號發(fā)起了進(jìn)攻,毫無意外,他陣亡了。。。
          中間彩蛋。
          男3號不甘心,原地復(fù)活,想再戰(zhàn)一回。在一個(gè)地方跌倒,咱們就換一個(gè)地方再跌。。。
          于是對女2號發(fā)起了進(jìn)攻。
          幾經(jīng)波折。
          男3號終于也成為了有牽絆的男人,不論未來有多久,只在乎曾經(jīng)擁有過。
          男4一看:這也沒我啥事兒了啊。
          以上的過程其實(shí)就是經(jīng)典的匈牙利算法,求解二分圖的最大匹配問題。

          03
          匈牙利算法
          二分圖
          定義:設(shè)G=(V,E)是一個(gè)無向圖,頂點(diǎn)集V可分割為兩個(gè)互不相交的子集X,Y,并且圖中每條邊關(guān)聯(lián)的兩個(gè)頂點(diǎn)都分屬于這兩個(gè)互不相交的子集,兩個(gè)子集內(nèi)的頂點(diǎn)不相鄰。
          判斷是否為二分圖的充要條件:G至少有兩個(gè)頂點(diǎn),且其所有回路的長度均為偶數(shù)。
          判斷方法:染色法
          • 開始對任意一未染色的頂點(diǎn)染色
          • 判斷其相鄰的頂點(diǎn)中,若未染色則將其染上和相鄰頂點(diǎn)不同的顏色;
          • 若已經(jīng)染色且顏色和相鄰頂點(diǎn)的顏色相同則說明不是二分圖,若顏色不同則繼續(xù)判斷
          可用bfs或者dfs。
          匹配
          在二分圖G的子圖M中,M的邊集E中的任意兩條邊都不依附于同一個(gè)頂點(diǎn),則稱M是一個(gè)匹配
          飽和點(diǎn)
          匹配M的邊集所關(guān)聯(lián)的點(diǎn)為飽和點(diǎn),否則為非飽和點(diǎn)。如上圖:
          • 的飽和點(diǎn):。
          • 的飽和點(diǎn):。
          交錯(cuò)路
          定義:圖G的一條路徑,且路徑中的邊在屬于M和不屬于M中交替出現(xiàn)。
          增廣路(非網(wǎng)絡(luò)流中的定義)
          定義:一條交錯(cuò)路,且該交錯(cuò)路的起點(diǎn)和終點(diǎn)都為匹配M的非飽和點(diǎn)。
          如上圖,交錯(cuò)路1是增廣路;交錯(cuò)路2不是增廣路,因?yàn)榻K點(diǎn)不是非飽和點(diǎn)。
          由增廣路推出以下結(jié)論:
          • 路徑的邊數(shù)為奇數(shù),第一條邊和最后一條邊都不屬于M
          • 將路徑中的邊的匹配方式取反操作,會(huì)得到更大的匹配M',匹配數(shù)加1
          • M為圖G的最大匹配等價(jià)于不存在M的增廣路
          匈牙利算法核心思想:
          • 1) 初始匹配M為空
          • 2) 找出一條增廣路徑p,取反操作得到更大的匹配M'代替M
          • 3) 重復(fù)步驟2),直到找不出增廣路為止


          04
          代碼實(shí)現(xiàn)
          變量定義及初始化
          const int MAXM = 200, MAXN = 200;
          bool map[MAXN][MAXM] = {false}, visit[MAXM];
          int n, m, x[MAXM], y[MAXN], ans = 0;
          初始化
          void init() {
              memset(x, 0xff, MAXM * 4);
              memset(y, 0xff, MAXN * 4);
              memset(mapfalse, MAXN * MAXM);

              int num, temp;
              cin >> n >> m;
              for (int i = 0; i < n; ++i) {
                  cin >> num;
                  for (int j = 0; j < num; ++j) {
                      cin >> temp;
                      map[i][temp - 1] = true;
                  }
              }
          }
          遞歸尋找增廣路
          bool hungary(int u) {
              for (int i = 0; i < m; ++i) {
                  if (!visit[i] && map[u][i]) {
                      visit[i] = true;
                      if (y[i] == -1 || hungary(y[i])) {
                          x[u] = i;
                          y[i] = u;
                          return true;
                      }
                  }
              }
              return false;
          }
          遍歷所有點(diǎn)
          int main() {
              init();
              for (int i = 0; i < n; ++i) {
                  if (x[i] == -1) {
                      memset(visit, false, MAXM);
                      if (hungary(i)) {
                          ans++;
                      }
                  }
              }
              cout << ans << endl;

              return 0;
          }
          測試數(shù)據(jù)
          輸入
          5 5
          2 2 5
          3 2 3 4
          2 1 5
          3 1 2 5
          1 2
          輸出
          4



          關(guān)注我,漲知識
          原創(chuàng)不易,感謝分享
          轉(zhuǎn)發(fā),點(diǎn)贊,在看!


          瀏覽 36
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  嫩草久久99www亚洲红桃 | 人人干人人看人人摸 | 伊人色色视频 | 一级a看片在线观看 | www.xxxx.日本 |