• <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邊表的內容就到此為止了。這真是一種有大用的數據結構。
            亚洲精品高清久久| 蜜臀av性久久久久蜜臀aⅴ | 老男人久久青草av高清| 精品国产乱码久久久久软件| 天天爽天天狠久久久综合麻豆| 欧美亚洲国产精品久久蜜芽| 亚洲国产小视频精品久久久三级 | 亚洲国产精品婷婷久久| 久久亚洲精品国产亚洲老地址| 日本强好片久久久久久AAA| 狠狠久久综合伊人不卡| 久久精品天天中文字幕人妻| 香港aa三级久久三级老师2021国产三级精品三级在| 久久久久高潮综合影院| 久久久久无码专区亚洲av| 国产亚洲色婷婷久久99精品| 性做久久久久久免费观看| 国产A级毛片久久久精品毛片| 一本色道久久88精品综合| 久久综合久久伊人| 99久久精品这里只有精品| 精品综合久久久久久888蜜芽| 人妻无码精品久久亚瑟影视| 久久国产美女免费观看精品| 久久青青草原精品影院| www久久久天天com| 色综合久久中文字幕无码| 色狠狠久久综合网| 欧美久久综合九色综合| 久久精品中文字幕有码| 久久国产高清一区二区三区| 91亚洲国产成人久久精品网址| 精品久久777| 久久91精品国产91久久小草 | 欧美大战日韩91综合一区婷婷久久青草 | 久久精品国产亚洲av高清漫画| 无码八A片人妻少妇久久| 性做久久久久久久久久久| 国内精品久久久久久久久| 国产精品无码久久久久| 岛国搬运www久久|