1. 程式人生 > >圖論入門———深度優先搜尋實現二分圖判定(dfs染色)

圖論入門———深度優先搜尋實現二分圖判定(dfs染色)

這周開始圖論的學習

簡要的瞭解一下圖的概念,以及表示、儲存的方法。

主要就是鄰接矩陣鄰接表兩種方式 鄰接矩陣就不說了比較好實現

鄰接表則主要用到不同的容器,比如vector

使用鄰接表的主要思路是對每一個頂點都建立一個vector容器,當它和另一個頂點有邊的時候就將該頂點的編號插入vector中,注意無向表還要反過來插入一次

當使用類或者結構體來儲存圖的頂點和邊時就可以新增眾多的屬性來擴充套件

接下來就是圖的搜尋,先以最基本的深度優先搜尋為例 其實很簡單,就是一個頂點走到頭再回來走下一支

現在有一個基本的問題,我們如何判斷一個圖是否是二分圖呢

最簡單的思路無非是窮舉,對每個頂點我們都可以有兩種顏色,採用搜尋的思路,如果能走出一條滿足任意兩個頂點顏色的路徑就可以了。

具體的實現方法參考一下書本,大概可以這樣想:

從一個頂點出發,把所有它相鄰的頂點染成另一個顏色。不停的繼續這一個過程,一層一層的染色。如果中間不出現矛盾情況(即相鄰的頂點同色)就判定為二分圖,否則立即返回換一個沒有染色的頂點重新嘗試(這個的原理需要好好理解)

程式碼:

/*
最基礎的圖論問題,算是對儲存結構的熟悉。
二分圖判定問題,使用鄰接表實現(vector)
*/
# include<iostream>
# include<vector>

using namespace std;

const int MAX_V = 1000;

int V,E;

vector<int> G[MAX_V];//新建了一個圖,G陣列中的每一個元素都是一個頂點,對應著一個vector,其中包含了它指向的頂點。

//沒有設定邊的屬性,僅用一個int表示指向的頂點。

int color[MAX_V];//記錄頂點的顏色(只有兩種,1或-1)

bool dfs(int v,int c)
{
    color[v] = c;//將頂點v染成顏色c
    
    for (int i = 0; i < G[v].size(); i++)
    {
        if (color[G[v][i]] == c)
            return false;
        /*
        簡要說明:
        首先需要理解G[v][i]的含義!是指頂點v的第i條邊指向的頂點!
        上面的表示,如果相鄰的頂點同色,就剪掉這一枝,返回false
        */
        if (color[G[v][i]] == 0 && !dfs(G[v][i], -c))
            return false;
        //如果相鄰的頂點還沒有染色就把它染成-c
    }

    return true;
    //如果都染色了返回true
}

void solve()
{
    for (int i = 0; i < V; i++)
    {
        if (color[i] == 0)
        {
            if (!dfs(i, 1))
            {
                printf("No\n");
                return;
            }
        }
    }

    printf("Yes\n");
}

int main()
{
    cin >> V >> E;

    for (int i = 0; i < E; i++)
    {
        int s, t;
        cin >> s >> t;
        G[s].push_back(t);//從s向t連邊
        G[t].push_back(s);//因為是無向圖反過來再連線一次
    }

    solve();

    //system("pause");

    return 0;
}