题意:中文题
思路:首先男女各人用两种颜色,那么用A不用B和用B不用A时候的方案数是等价的,那么我们可以强行固定男先用A染色,女生先用C染色,最后方案数*4就是最后总的方案数。先用DFS/BFS把相同的城市标号,然后再次DFS/BFS把图的领接矩阵构造出来,然后再遍历一遍把邻接表构造出来。
使用邻接表是因为可以快速地查找与它相邻的城市,而先构造邻接矩阵是因为要判重,然后直接固定一下他们染色的顺序就直接爆搜就可以了。实现起来还是有挺多细节的吧。
吐槽:用vector 19964MS卡过去了,自己实现的前向星10284MS。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
char mp[35][35];
int vis[35][35],flag[35][35],mapp[35][35];
//vector<int>e[35];
struct Edge
{
int v,nxt;
}edge[1005];
int head[35],num;
void add(int u,int v)
{
edge[num].v=v;
edge[num].nxt = head[u];
head[u]=num++;
}
int color[35];
int cnt=0;
long long ans=0;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int r,c;
void bfs(int x,int y)
{
++cnt;
queue<pair<int,int> >q;
q.push(make_pair(x,y));
while(!q.empty())
{
pair<int,int> t = q.front();
q.pop();
vis[t.first][t.second]=cnt;
for(int i = 0;i<4;i++)
{
int dx = t.first +dir[i][0];
int dy = t.second+dir[i][1];
if(dx<0 || dx>=r || dy<0||dy>=c)continue;
if(vis[dx][dy] || mp[dx][dy]!=mp[t.first][t.second])continue;
q.push(make_pair(dx,dy));
}
}
}
void bfs1(int x,int y)
{
queue<pair<int,int> >q;
q.push(make_pair(x,y));
while(!q.empty())
{
pair<int,int> t = q.front();
q.pop();
flag[t.first][t.second]=1;
for(int i = 0;i<4;i++)
{
int dx = t.first +dir[i][0];
int dy = t.second+dir[i][1];
if(dx<0 || dx>=r || dy<0||dy>=c)continue;
if(flag[dx][dy])continue;
if(vis[t.first][t.second]!=vis[dx][dy])
{
mapp[vis[t.first][t.second]][vis[dx][dy]]=mapp[vis[dx][dy]][vis[t.first][t.second]]=1;
continue;
}
q.push(make_pair(dx,dy));
}
}
}
bool check(int u,int co)
{
for(int i = head[u];i!=-1;i=edge[i].nxt)
if(color[edge[i].v]==co)return 0;
return 1;
//for(int i = 0;i<e[u].size();i++)
// if(color[e[u][i]]==co)return 0;
// return 1;
}
//当前第几个城市 A用了几个 B用了几个 C用了几个 D用了几个
void dfs(int pos,int a,int b,int c,int d)
{
if(pos==cnt+1)
{
if(a&&b&&c&&d)ans++;
return;
}
color[pos]=0;
if(check(pos,0))dfs(pos+1,a+1,b,c,d);
color[pos]=1;
if(check(pos,1) && a)dfs(pos+1,a,b+1,c,d);
color[pos]=2;
if(check(pos,2) && c+d<5)dfs(pos+1,a,b,c+1,d);
color[pos]=3;
if(check(pos,3) && c+d<5 && c)dfs(pos+1,a,b,c,d+1);
}
void init()
{
memset(vis,0,sizeof(vis));
memset(flag,0,sizeof(flag));
memset(color,0,sizeof(color));
// for(int i = 0;i<35;i++)e[i].clear();
memset(mp,0,sizeof(mp));
memset(mapp,0,sizeof(mapp));
ans = 0;
cnt = 0;
memset(head,-1,sizeof(head));
num=0;
}
int cas = 1;
int main()
{
while(scanf("%d%d",&r,&c)!=EOF)
{
init();
for(int i = 0;i<r;i++)scanf("%s",mp[i]);
//get id
for(int i = 0;i<r;i++)
for(int j = 0;j<c;j++)
if(!vis[i][j])bfs(i,j);
for(int i = 0;i<r;i++)
for(int j = 0;j<c;j++)
if(!flag[i][j])bfs1(i,j);
for(int i = 1;i<=cnt;i++)
for(int j = 1;j<i;j++)
if(i!=j && mapp[i][j])
{
add(i,j);
// e[i].push_back(j);
}
dfs(1,0,0,0,0);
printf("Case %d: %lld\n",cas++,ans*4);
}
}