回溯法-圖的m着色問題

本文參考https://blog.csdn.net/kevin_cyj/article/details/50385575

 問題描述與思想概述
(1)、問題的提出
       給定無向連通圖G和m種不同的顏色。用這些顏色爲圖G的各頂點着色,每個頂點着一種顏色。是否有一種着色法使G中每條邊的2個頂點着不同顏色。這個問題是圖的m可着色判定問題。若一個圖最少需要m種顏色才能使圖中每條邊連接的2個頂點着不同顏色,則稱這個數m爲該圖的色數。求一個圖的色數m的問題稱爲圖的m可着色優化問題。

輸入:無向圖,m

輸出:如果能,則輸出方案

四色問題是m圖着色問題的一個特例,根據四色原理,證明平面或球面上的任何地圖的所有區域都至多可用四種顏色來着色,並使任何兩個有一段公共邊界的相鄰區域沒有相同的顏色。這個問題可轉換成對一平面圖的4-着色判定問題(平面圖是一個能畫於平面上而邊無任何交叉的圖)。將地圖的每個區域變成一個結點,若兩個區域相鄰,則相應的結點用一條邊連接起來。多年來,雖然已證明用5種顏色足以對任一幅地圖着色,但是一直找不到一定要求多於4種顏色的地圖。直到1976年這個問題才由愛普爾,黑肯和考西利用電子計算機的幫助得以解決。他們證明了4種顏色足以對任何地圖着色。

(2)、問題的處理
如果把每一個區域收縮爲一個頂點,把相鄰兩個區域用一條邊相連接,就可以把一個區域圖抽象爲一個平面圖。

用m種顏色爲圖中的每個頂點着色,要求每個頂點着一種顏色,並使相鄰兩頂點之間有着不同的顏色

如圖:

 

 

 

 

一個例子

着色問題的解空間樹爲:

 

可以看到約束函數爲:i點有m種着色可能性,但若與某個已着色的點相連且顏色相同,則不選擇這種着色可能性

3、練習題

https://www.luogu.org/problem/P2819

 

代碼:

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int n;//n個節點
int m;//m種顏色
int mm[100][100];//記錄圖的鄰接矩陣
int x[100];//記錄樹的一條枝,即圖着色的一種可能性,x[i]=1,2,3..k..n代表第節點i顏色爲k
int bestx[100];
int sum=0;//用來記錄當前可行的着色方案
//分析本題的約束函數爲兩節點相連且同種顏色時,不會繼續往下發展這種可能性
bool ok(int i)
{
    int j;
    for(j=1;j<=n;j++)
    {
        if((mm[i][j]==1)&&(x[i]==x[j]))//我到底和哪些節點相連且顏色一樣
        {
            return false;
        }
    }
    return true;
}
void dfs(int i)
{
    int j;
    if(i>n)
    {
        sum++;
        for(j=1;j<=n;j++)
        {
            bestx[j]=x[j];//記錄一條枝(記錄一種着色的可能性)
        }
    }
    else
    {
        for(j=1;j<=m;j++)//在i節點處檢測它自己可能填的m種可能性
        {
             x[i]=j;//i節點選定了一種顏色
            if(ok(i))//通過約束函數去掉不合理的顏色可能性
            {
                 dfs(i+1);//活節點轉移到下一層的第i+1個節點
            }

             x[i]=0;//無實義,爲i繼續換別的顏色可能性
        }
    }
}
int main()
{
    int t,k;
    int i,j;
    scanf("%d %d %d",&n,&k,&m);//k是k條邊
    for(t=0;t<k;t++)
    {
        scanf("%d %d",&i,&j);
        mm[i][j]=1;
        mm[j][i]=1;
    }
    dfs(1);
    printf("%d",sum);
    return 0;
}

 

發佈了15 篇原創文章 · 獲贊 2 · 訪問量 5015
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章