• <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综合影院| 日本人妻丰满熟妇久久久久久| 91久久精品视频| 国产福利电影一区二区三区,免费久久久久久久精 | 麻豆一区二区99久久久久| 久久久国产精品福利免费| 久久亚洲欧洲国产综合| 午夜久久久久久禁播电影| 91久久成人免费| 伊人久久大香线焦AV综合影院| 久久精品成人免费网站| 亚洲欧洲中文日韩久久AV乱码| 日韩精品无码久久久久久| 久久久久亚洲精品中文字幕| 色综合久久久久综合体桃花网| 久久精品国产国产精品四凭 | 久久久午夜精品| 国产精久久一区二区三区| 久久99精品国产麻豆宅宅| 国产亚洲色婷婷久久99精品91| 久久综合噜噜激激的五月天| 日韩中文久久| 精品国产婷婷久久久| 久久这里只有精品久久| 国产精品久久永久免费| 亚洲国产精品成人久久| 久久亚洲精品国产亚洲老地址 | 久久久久久久久久久免费精品| 久久超碰97人人做人人爱| 无码伊人66久久大杳蕉网站谷歌| 岛国搬运www久久| 亚洲综合精品香蕉久久网97 | 久久亚洲欧洲国产综合| 国产免费久久精品99久久| 久久精品国产91久久综合麻豆自制 | 国产午夜精品久久久久九九| 久久er国产精品免费观看2| 久久se精品一区二区| 久久免费精品视频| 久久成人国产精品一区二区| 国产91久久综合|