• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            搞完了網(wǎng)絡(luò)流圖,搞完了一般圖,最后應(yīng)該是二分圖了(在本沙茶知道的圖的范圍內(nèi))
            二分圖的邊有些特別,邊<a, b>并不是表示從a到b的邊,而是從X方點a(簡記為Xa)到Y(jié)方點b(簡記為Yb)的邊。在二分圖中,邊其實是無向的,但由于大多數(shù)引用的時候都是X方點引用Y方點,所以可以把邊看成有向的(如果實在要逆向引用的話,加一條逆向邊吧囧……)
            邊類型定義(和一般圖完全一致。這里是不帶權(quán)的,如果像KM算法里面有帶權(quán)邊,加一個len域即可):
            struct edge {
                
            int a, b, pre, next;
            } ed[MAXM];
            關(guān)鍵是在初始化表頭的時候,設(shè)圖中有NX個X方點和NY個Y方點,則單點鏈表數(shù)其實只有NX。故只需弄NX個表頭即可:
            void init_d()
            {
                re(i, nx) ed[i].a 
            = ed[i].pre = ed[i].next = i;
                
            if (nx % 2) m = nx + 1else m = nx;
            }
            然后是加邊,和一般圖完全一致:
            void add_edge(int a, int b)
            {
                ed[m].a 
            = a; ed[m].b = b; ed[m].pre = ed[a].pre; ed[m].next = a; ed[a].pre = m; ed[ed[m].pre].next = m++;
            }
            差不多就搞完了。下面是用Dancing Link邊表實現(xiàn)的Hungary算法的深度優(yōu)先遍歷部分:
            bool dfs(int x)
            {
                vst[x] 
            = 1;
                
            int y, x1;
                
            for (int p=ed[x].next; p != x; p=ed[p].next) {
                    y 
            = ed[p].b; x1 = xz[y];
                    
            if (x1 == -1 || !vst[x1] && dfs(x1)) {
                        xz[y] 
            = x; return 1;
                    }
                }
                
            return 0;
            }
            這里xz[y]指的是y所匹配的X方點編號(若y是未蓋點則xz[y]=-1),vst[x]是X方點x是否被訪問的標(biāo)志,在每次遍歷前,vst都要全部清零。

            【應(yīng)用實例】PKU1087
            題意很難懂,其實就是:房間里有N個插座,每個插座都有一個型號(沒有兩個插座的型號相同),現(xiàn)在要把M個用電器插到這N個插座里,每個用電器有一個默認(rèn)型號,表示該用電器只能插到其默認(rèn)型號的插座里(有可能有的用電器的默認(rèn)型號不與房間里的任意一個插座對應(yīng),如樣例中的X型號)。有K種適配器(每種適配器可以用無限次),每一種適配器都有兩個參數(shù)S1和S2,表示該種適配器使用一次可以將某個默認(rèn)型號為S1的用電器的默認(rèn)型號改為S2(同一個用電器可以被多次改變默認(rèn)型號)。問在使用了若干次適配器后,最少有多少個用電器插不到插座里?
            首先將每種型號作為一個點,若某種適配器的兩個參數(shù)分別為S1和S2則連邊<S1, S2>,對這個有向圖求傳遞閉包。然后再建一個二分圖,X方點表示用電器,Y方點表示插座,若Xi的初始默認(rèn)型號在一開始建的有向圖中可以到達(dá)Yj的型號(用傳遞閉包直接得到),則連邊(Xi, Yj)。對這個二分圖求最大匹配,則(M - 最大匹配值)就是結(jié)果。
            代碼:
            #include <iostream>
            #include 
            <stdio.h>
            #include 
            <string.h>
            #include 
            <string>
            using namespace std;
            #define re(i, n) for (int i=0; i<n; i++)
            const int MAXN = 500, MAXM = 250500, MAXLEN = 50, INF = ~0U >> 2;
            struct edge {
                
            int a, b, pre, next;
            } ed[MAXM];
            int n, nx, ny, m, xt[MAXN], yt[MAXN], xz[MAXN], res = 0;
            bool f[MAXN][MAXN], vst[MAXN];
            string nm[MAXN];
            void init()
            {
                
            string s1, s2;
                
            char s01[MAXLEN], s02[MAXLEN], ch;
                scanf(
            "%d"&ny); ch = getchar();
                re(i, ny) {gets(s01); nm[i] 
            = s01; yt[i] = i;} n = ny;
                scanf(
            "%d"&nx); ch = getchar();
                re(i, nx) {
                    scanf(
            "%s %s", s01, s02); ch = getchar(); xt[i] = n;
                    re(j, n) 
            if (nm[j] == s02) {xt[i] = j; break;}
                    
            if (xt[i] == n) nm[n++= s02;
                }
                
            int z, t1, t2;
                scanf(
            "%d"&z); ch = getchar();
                re(i, z) {
                    scanf(
            "%s %s", s01, s02); ch = getchar();
                    t1 
            = n; re(j, n) if (nm[j] == s01) {t1 = j; break;}
                    
            if (t1 == n) nm[n++= s01;
                    t2 
            = n; re(j, n) if (nm[j] == s02) {t2 = j; break;}
                    
            if (t2 == n) nm[n++= s02;
                    f[t1][t2] 
            = 1;
                }
                re(i, n) f[i][i] 
            = 1;
            }
            void add_edge(int a, int b)
            {
                ed[m].a 
            = a; ed[m].b = b; ed[m].pre = ed[a].pre; ed[m].next = a; ed[a].pre = m; ed[ed[m].pre].next = m++;
            }
            void prepare()
            {
                re(k, n) re(i, n) re(j, n) f[i][j] 
            = f[i][j] || f[i][k] && f[k][j];
                re(i, nx) ed[i].a 
            = ed[i].pre = ed[i].next = i;
                
            if (nx % 2) m = nx + 1else m = nx;
                re(i, nx) {
                    
            int t0 = xt[i];
                    re(j, ny) 
            if (f[t0][j]) add_edge(i, j);
                }
            }
            bool dfs(int x)
            {
                vst[x] 
            = 1;
                
            int y, x1;
                
            for (int p=ed[x].next; p != x; p=ed[p].next) {
                    y 
            = ed[p].b; x1 = xz[y];
                    
            if (x1 == -1 || !vst[x1] && dfs(x1)) {
                        xz[y] 
            = x; return 1;
                    }
                }
                
            return 0;
            }
            void solve()
            {
                re(i, ny) xz[i] 
            = -1;
                re(i, nx) {
                    re(j, ny) vst[j] 
            = 0;
                    res 
            += dfs(i);
                }
            }
            void pri()
            {
                printf(
            "%d\n", nx - res);
            }
            int main()
            {
                init();
                prepare();
                solve();
                pri();
                
            return 0;
            }
            有關(guān)圖的Dancing Link邊表的內(nèi)容就到此為止了。這真是一種有大用的數(shù)據(jù)結(jié)構(gòu)。
            人妻精品久久无码区| 精品久久综合1区2区3区激情 | 久久人人爽人人爽人人片AV不| 一本色道久久综合狠狠躁| 久久久久亚洲精品日久生情| 国内精品久久久久影院薰衣草| 亚洲第一极品精品无码久久| AV无码久久久久不卡蜜桃| 久久精品免费大片国产大片| 久久精品国产乱子伦| 久久亚洲国产欧洲精品一| 欧美色综合久久久久久| 久久国产亚洲高清观看| 青青青青久久精品国产h久久精品五福影院1421 | 久久免费美女视频| 国产三级精品久久| 久久精品亚洲日本波多野结衣| 国内精品免费久久影院| 久久国产高潮流白浆免费观看| 久久久久女教师免费一区| 久久国产欧美日韩精品| 亚洲精品午夜国产va久久| 久久精品国产亚洲网站| 亚洲精品乱码久久久久久自慰| 国产午夜福利精品久久| 精品永久久福利一区二区 | 国产亚洲精午夜久久久久久| 久久亚洲中文字幕精品有坂深雪| 久久综合日本熟妇| 精品国产91久久久久久久a| 久久亚洲国产中v天仙www| 99久久成人国产精品免费| 久久亚洲精品人成综合网| 久久亚洲sm情趣捆绑调教| 欧美日韩精品久久久久| 久久精品国产精品亚洲| 久久99精品免费一区二区| 久久婷婷久久一区二区三区 | 久久WWW免费人成—看片| 久久久久久综合一区中文字幕| 99久久综合狠狠综合久久|