• <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>
            搞完了網絡流圖,搞完了一般圖,最后應該是二分圖了(在本沙茶知道的圖的范圍內)
            二分圖的邊有些特別,邊<a, b>并不是表示從a到b的邊,而是從X方點a(簡記為Xa)到Y方點b(簡記為Yb)的邊。在二分圖中,邊其實是無向的,但由于大多數引用的時候都是X方點引用Y方點,所以可以把邊看成有向的(如果實在要逆向引用的話,加一條逆向邊吧囧……)
            邊類型定義(和一般圖完全一致。這里是不帶權的,如果像KM算法里面有帶權邊,加一個len域即可):
            struct edge {
                
            int a, b, pre, next;
            } ed[MAXM];
            關鍵是在初始化表頭的時候,設圖中有NX個X方點和NY個Y方點,則單點鏈表數其實只有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邊表實現的Hungary算法的深度優先遍歷部分:
            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是否被訪問的標志,在每次遍歷前,vst都要全部清零。

            【應用實例】PKU1087
            題意很難懂,其實就是:房間里有N個插座,每個插座都有一個型號(沒有兩個插座的型號相同),現在要把M個用電器插到這N個插座里,每個用電器有一個默認型號,表示該用電器只能插到其默認型號的插座里(有可能有的用電器的默認型號不與房間里的任意一個插座對應,如樣例中的X型號)。有K種適配器(每種適配器可以用無限次),每一種適配器都有兩個參數S1和S2,表示該種適配器使用一次可以將某個默認型號為S1的用電器的默認型號改為S2(同一個用電器可以被多次改變默認型號)。問在使用了若干次適配器后,最少有多少個用電器插不到插座里?
            首先將每種型號作為一個點,若某種適配器的兩個參數分別為S1和S2則連邊<S1, S2>,對這個有向圖求傳遞閉包。然后再建一個二分圖,X方點表示用電器,Y方點表示插座,若Xi的初始默認型號在一開始建的有向圖中可以到達Yj的型號(用傳遞閉包直接得到),則連邊(Xi, Yj)。對這個二分圖求最大匹配,則(M - 最大匹配值)就是結果。
            代碼:
            #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;
            }
            有關圖的Dancing Link邊表的內容就到此為止了。這真是一種有大用的數據結構。
            人妻精品久久久久中文字幕| 久久久久久国产精品无码下载| 国产精品久久久久久久app| 亚洲午夜久久久久妓女影院| 久久人人爽人人爽人人片AV不 | 久久人人爽人人爽人人片AV东京热| 国产成人精品久久| 97精品伊人久久大香线蕉app| 国产精品热久久无码av| 99久久综合国产精品免费| 91精品国产乱码久久久久久 | 2021国内久久精品| 91精品国产乱码久久久久久| 中文精品99久久国产 | 久久久国产精华液| 久久婷婷五月综合国产尤物app| 久久影视综合亚洲| 99久久无码一区人妻| 97r久久精品国产99国产精| 亚洲精品第一综合99久久| 女人香蕉久久**毛片精品| 麻豆成人久久精品二区三区免费| 91精品日韩人妻无码久久不卡| 热re99久久6国产精品免费| 久久久午夜精品| 无码人妻久久一区二区三区蜜桃| 久久青草国产精品一区| 精品久久久久久无码专区| 久久AV无码精品人妻糸列| 精品久久久久久久久免费影院| 久久久久久青草大香综合精品| 久久精品国产亚洲麻豆| 国产精品久久久久AV福利动漫| 99久久精品免费看国产一区二区三区| 最新久久免费视频| 久久婷婷五月综合成人D啪| 狠狠色狠狠色综合久久| 亚洲精品乱码久久久久久| 久久久久无码精品国产| 久久国产精品99精品国产| 久久99精品国产自在现线小黄鸭|