非遞迴的n頂點m顏色點著色問題
阿新 • • 發佈:2019-01-22
這應該是普及組都應該會的玩意吧。。。
做組合數學的數學題時,做到了一個求6頂點4顏色點著色種數的題,恕我直言,我不會用漂亮的方法來做,然而我這個不氪金的網遊一樣的腦袋就想著去寫個程式試試,結果發現我居然連深搜都無法寫出正確結果。再加上昨天CF史上新低,居然一題都沒過嚇壞了我們學校的學長。是時候反思一下了,省選臨近,雖然我是湊數的但是也不能掉以輕心啊。
剛剛是讀不讀都沒什麼影響的前言,下面正文。
如前面所說,我這樣反覆思之,細思極恐以後,趕緊去看了別人的部落格,後來看到了一個不遞迴的方法 趕緊學了。參考了這個qinyg大神寫的方法,雖然我不認識不過萬分感謝。
更讓我細思極恐的是,我居然第一次看無法完全理解這個方法,它不會重複計數嗎?事實再一次證明我的腦殘,我就是個zz吧,然後我就把數學卷子上的資料帶進去調才明白這是怎麼運作的,唉
我覺得現在的我思維有點凍結 我也不知道為什麼啊 qaq
過程是這樣的:最後一個else當且僅當k==n,color[k]>=m後的迴圈退回來以後,k為這個迴圈的k減一,由於是color[k]++所以會去嘗試不同的顏色;順序:從最後一個頂點嘗試完後退回倒數第二個,嘗試完到最後一個點後再回到倒數第二個,倒數第二個嘗試完後繼續回退。。。直至所有點嘗試完畢。
我相信大家的智商肯定比我這個弱智要高,給出程式碼qwq這是固定的6頂點4顏色方法(因為數學卷子上資料是這個)當然可以改為普通的n頂點m顏色方法,scanf一個n,m就完了
//這是固定的6頂點4顏色方法(因為數學卷子上資料是這個)
//當然可以改為普通的n頂點m顏色方法,scanf一個n,m就完了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn=100;
int n=6;
int m=4;
int ans=0;
vector<int > g[maxn];
int color[maxn];
void addedge(int from,int to)
{
g[from].push_back(to);
g[to].push_back(from);
}
bool check(int v)
{
for(unsigned i=0;i<g[v].size();i++)
{
int u=g[v][i];
if(color[u]!=0 && color[u]==color[v])
{
return false;
}
}
return true;
}
void colored()
{
int k=1;
memset(color,0,sizeof(color));
while(k>=1)
{
color[k]++;
while(color[k]<=m)
{
if(check(k))
{
break;
}
else
{
color[k]++;
}
}
if(k==n && color[k]<=m)
{
ans++;
}
else if(k<n && color[k]<=m)
{
k++;
}
else
{
color[k]=0;
k--;//當且僅當k==n,color[k]>=m後的迴圈
//退回來以後,k為這個迴圈的k減一,由於是color[k]++
//所以會去嘗試不同的顏色
//順序:從最後一個頂點嘗試完後退回倒數第二個,嘗試完到最後一個點
//後再回到倒數第二個,倒數第二個嘗試完後繼續回退。。。直至所有點嘗試完畢。
}
}
}
int main()
{
int from,to;
while(scanf("%d%d",&from,&to)==2)
{
addedge(from,to);
}
colored();
printf("%d\n",ans);
return 0;
}
那麼繼續吧 我這個智障的oi歷程