回溯法(四)——圖的m着色問題


1 題目描述

  給定無向連通圖G=(V, E)m種不同的顏色,用這些顏色為圖G的各頂點着色,每個頂點着一種顏色。是否有一種着色法使G中相鄰的兩個頂點有不同的顏色?

  這個問題是圖的m可着色判定問題。若一個圖最少需要m種顏色才能使圖中每條邊連接的兩個頂點着不同顏色,則稱這個數m為該圖的色數。求一個圖的色數m的問題稱為圖的m可着色優化問題。

  編程計算:給定圖G=(V, E)m種不同的顏色,找出所有不同的着色法和着色總數。

2 輸入

  第一行是頂點的個數n(2≤n≤10),顏色數m(1≤m≤n);
  接下來是頂點之間的相互關系:a b,表示a和b相鄰。當a,b同時為0時表示輸入結束。

3 輸出

  輸出所有的着色方案,表示某個頂點塗某種顏色號,每個數字的后面有一個空格。最后一行是着色方案總數。

4 樣例輸入

5 4
1 3
1 2
1 4
2 3
2 4
2 5
3 4
4 5
0 0

5 樣例輸出

1 2 3 4 1 
1 2 3 4 3 
1 2 4 3 1 
1 2 4 3 4 
1 3 2 4 1 
1 3 2 4 2 
1 3 4 2 1 
1 3 4 2 4 
1 4 2 3 1 
1 4 2 3 2 
1 4 3 2 1 
1 4 3 2 3 
2 1 3 4 2 
2 1 3 4 3 
2 1 4 3 2 
2 1 4 3 4 
2 3 1 4 1 
2 3 1 4 2 
2 3 4 1 2 
2 3 4 1 4 
2 4 1 3 1 
2 4 1 3 2 
2 4 3 1 2 
2 4 3 1 3 
3 1 2 4 2 
3 1 2 4 3 
3 1 4 2 3 
3 1 4 2 4 
3 2 1 4 1 
3 2 1 4 3 
3 2 4 1 3 
3 2 4 1 4 
3 4 1 2 1 
3 4 1 2 3 
3 4 2 1 2 
3 4 2 1 3 
4 1 2 3 2 
4 1 2 3 4 
4 1 3 2 3 
4 1 3 2 4 
4 2 1 3 1 
4 2 1 3 4 
4 2 3 1 3 
4 2 3 1 4 
4 3 1 2 1 
4 3 1 2 4 
4 3 2 1 2 
4 3 2 1 4 
Total=48

6 求解思路

  使用回溯法,具體步驟是將cur=1傳入backtrack(),即從第一個開始塗色。

  塗的時候從顏色1開始到m,每當塗上一個色,要用ok(cur)判斷第cur個點是否可以塗這個色,不可以的話就不再往下塗了,改試另一個顏色,可以的話就繼續……執行完這個for循環就回溯。

  當cur>n的時候即前n個點都塗完了,然后輸出結果並cou++計數。

7 C++版本代碼如下

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int n, m;
int a = 1, b = 1;
int cou = 0;
// 鄰接矩陣
int graph[20][20];
// 着色表
int color[20];

// 判斷是否可以着色
bool ok(int c)
{
    for(int k=1;k<=n;k++)
    {
        if(graph[c][k]&&color[c]==color[k])
        {
            return false;
        }
    }
    return true;
}

void backtrack(int cur)
{
    if(cur>n)
    {
        for(int i=1;i<=n;i++)
        {
            printf("%d ",color[i]);
        }
        cou++;
        printf("\n");
    }
    else
    {
        for(int i=1;i<=m;i++)
        {
            color[cur]=i;
            if(ok(cur))
            {
                backtrack(cur+1);
            }
            color[cur]=0;
        }
    }
}

int main()
{
    memset(graph, 0, sizeof(graph));
    memset(color, 0, sizeof(color));
    scanf("%d %d", &n, &m);
    while(scanf("%d %d", &a, &b) != EOF && a != 0 && b != 0)
    {
        graph[a][b] = 1;
        graph[b][a] = 1;
    }
    backtrack(1);
    printf("Total = %d", cou);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM