圖着色問題


圖上的染色問題算是一個挺有名的NP-完全問題了吧

題目描述

    給定無向連通圖G 和M 種不同的顏色,用這些顏色為圖G 的各頂點着色,每個頂點着一種顏色。如果有一種着色法使G 中每條邊的2 個頂點着不同的顏色,則稱這個圖是M 可着色的。圖的M 着色問題是對於給定圖G 和M 種顏色,找出所有不同的着色法。對於給定的無向連通圖G 和M 種不同的顏色,編程計算圖的所有不同的着色法。


輸入

   第一行有3 個正整數N,K 和M,表示給定的圖G 有N 個頂點和K 條邊,M 種顏色。頂點編號為1,2……,N。接下來的K 行中,每行有2 個正整數U, V,表示圖G 的一條邊(U,V)。

  數據范圍:1<N<=100 1<K<=2500 1<M<=6


輸出


  不同的着色方案數

 

樣例輸入


  5 8 4
  1 2
  1 3
  1 4
  2 3
  2 4
  2 5
  3 4
  4 5


樣例輸出


  48

 

我的解析:

 

    這道題是一道典型的搜索題,需要dfs和一點點優化(剪枝)。

  我們來看一下樣例給的這張圖。

    為什么是搜索?對於樣例來說,每個點我們都有4種顏色可以選擇,而在確定完一個點的顏色后又要選取其他點的顏色,並不能與它相連的點重復。於是馬上想到要進行搜索。

    搜索的過程:對於每個點,枚舉它可能被染的顏色。如果與它相連的點顏色和它相同,那么就換下一個顏色;如果哪個顏色也不能選,那就回到上一個點換顏色(回溯)……

  當確定完最后一個點的顏色后,這就是一個可行解,將答案增加1。

    我們在判斷哪個點與這個點(編號為n)連接並顏色相同時,本來是要遍歷一遍圖上的點的,而這樣會超時。其實不需要這樣做。只需遍歷從編號1 到 編號n-1 的點就行了,因為

  並沒有確定編號n以后的點的顏色。這樣相對於把點全遍歷一遍,能更快一點,算是一個優化吧。

我的代碼:

 

#include<cstdio>
#include<algorithm>
using namespace std;
int m,n,k;
int map[105][105];
int color[105];
int ans;
void a(int p)
{
    if(p == n+1)
    {
        ans++;
        return;
    }
    else
    {
        for(int i=1;i<=m;i++)
        {
            int mmp = false;
            for(int j=1;j<=p;j++)
            {
                if(map[p][j] == 1 && color[j] == i)
                {
                    mmp = true;
                    break;
                }
            }
            if(mmp == true) continue;
            color[p] = i;
            a(p+1);
            color[p] = 0;
        }
    }
}
int main()
{
//    freopen("color.in","r",stdin);
//    freopen("color.out","w",stdout);
    scanf("%d%d%d",&n,&k,&m);
    for(int i=1;i<=k;i++)
    {
        int d1,d2;
        scanf("%d%d",&d1,&d2);
        map[d1][d2] = 1;
        map[d2][d1] = 1;
    }
    a(1);
    printf("%d",ans);
    return 0;
}

 


免責聲明!

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



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