UVALive - 6116 Pattern Lock 题目链接 http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=37383
//题意是先判断图是否联通,其次看是否根据边能够 构成 一个合法的图 不能多边少边
//其中如果原图是 2-1-3 那么 实际看起来 1-2 2-3 1-3 都可以看作是相连的
//根据这个特性,若原图中含边2-1 2-3 我们可以给它补上1-3
//其次,在得到一条合法路径后,用之构建一个图时,如果路径是1-3,那么我们可以补上(1-2,2-3)道理同上
//从而在分别给原图与新图补边后,我们得到两个与我们视觉上看起来一样的图,如果两者完全匹配,就OK,反之NO
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
int n;
int given_map[10][10];
int connect_map[10][10];
int m=0;
int cnt;
int state;
int tmp[10];
int f[10][2];
int vis_1[10];
vector <int> map[10];
queue <int > single_head;
int vis[10];
int query(int x,int y) // 查询x与y是否联通
{
if (x==y) return 1; //自己与自己属于连通
vector<int>::iterator final = find( map[x].begin(), map[x].end(), y ); //查找y
if (final!=map[x].end()) return 1; //找到为连通
int i;
for (i=0;i<map[x].size();i++) //遍历map[x] vector
{
if ( vis[ map[x][i] ] ==0 ) // vis[]=0 表示没遍历过该点
{
vis[ map[x][i] ] =1; //标记已经遍历过,下次不再进入此点
int ans=query( map[x][i] ,y); // 递归查找
if (ans) return 1;
}
}
return 0;
}
int flag;
void linkmap() //把原图connect 补好,便于后面 与 新构造的图对比
{
if(vis_1[2]&&given_map[2][1]&&given_map[2][3])
given_map[1][3]=given_map[3][1]=1;
if(vis_1[8]&&given_map[8][7]&&given_map[8][9])
given_map[9][7]=given_map[7][9]=1;
if(vis_1[4]&&given_map[4][1]&&given_map[4][7])
given_map[1][7]=given_map[7][1]=1;
if(vis_1[6]&&given_map[6][3]&&given_map[6][9])
given_map[3][9]=given_map[9][3]=1;
if(vis_1[5]&&given_map[2][5]&&given_map[5][8])
given_map[2][8]=given_map[8][2]=1;
if(vis_1[5]&&given_map[6][5]&&given_map[5][4])
given_map[6][4]=given_map[4][6]=1;
if(vis_1[5]&&given_map[1][5]&&given_map[5][9])
given_map[9][1]=given_map[1][9]=1;
if(vis_1[5]&&given_map[7][5]&&given_map[5][3])
given_map[3][7]=given_map[7][3]=1;
}
void create_full() // 把得到的新图补齐
{
if(vis[2]&&connect_map[2][1]&&connect_map[2][3])
connect_map[1][3]=connect_map[3][1]=1;
if(vis[8]&&connect_map[8][7]&&connect_map[8][9])
connect_map[9][7]=connect_map[7][9]=1;
if(vis[4]&&connect_map[4][1]&&connect_map[4][7])
connect_map[1][7]=connect_map[7][1]=1;
if(vis[6]&&connect_map[6][3]&&connect_map[6][9])
connect_map[3][9]=connect_map[9][3]=1;
if(vis[5]&&connect_map[2][5]&&connect_map[5][8])
connect_map[2][8]=connect_map[8][2]=1;
if(vis[5]&&connect_map[6][5]&&connect_map[5][4])
connect_map[6][4]=connect_map[4][6]=1;
if(vis[5]&&connect_map[1][5]&&connect_map[5][9])
connect_map[9][1]=connect_map[1][9]=1;
if(vis[5]&&connect_map[7][5]&&connect_map[5][3])
connect_map[3][7]=connect_map[7][3]=1;
if(connect_map[1][3]||connect_map[3][1])
connect_map[1][2]=connect_map[2][1]=connect_map[2][3]=connect_map[3][2]=1;
if(connect_map[1][7]||connect_map[7][1])
connect_map[4][7]=connect_map[7][4]=connect_map[1][4]=connect_map[4][1]=1;
if(connect_map[9][3]||connect_map[3][9])
connect_map[9][6]=connect_map[6][9]=connect_map[6][3]=connect_map[3][6]=1;
if(connect_map[7][9]||connect_map[9][7])
connect_map[7][8]=connect_map[8][7]=connect_map[8][9]=connect_map[9][8]=1;
if(connect_map[1][9]||connect_map[9][1])
connect_map[1][5]=connect_map[5][1]=connect_map[5][9]=connect_map[9][5]=1;
if(connect_map[7][3]||connect_map[3][7])
connect_map[7][5]=connect_map[5][7]=connect_map[5][3]=connect_map[3][5]=1;
if(connect_map[8][2]||connect_map[2][8])
connect_map[5][2]=connect_map[2][5]=connect_map[8][5]=connect_map[5][8]=1;
if(connect_map[4][6]||connect_map[6][4])
connect_map[4][5]=connect_map[5][4]=connect_map[5][6]=connect_map[6][5]=1;
}
int search_legal(int x,int y) //查询 在解锁规则中 x与y能否连接
{
if (x==1)
{
if (y==2&&!vis[2]) return 1;
if (y==3&&!vis[3]) if (vis[2]) return 1;
if (y==4&&!vis[4]) return 1;
if (y==5&&!vis[5]) return 1;
if (y==6&&!vis[6]) return 1;
if (y==7&&!vis[7]) if (vis[4]) return 1;
if (y==8&&!vis[8]) return 1;
if (y==9&&!vis[9]) if (vis[5]) return 1;
}
if (x==2)
{
if (y==1&&!vis[1]) return 1;
if (y==3&&!vis[3]) return 1;
if (y==4&&!vis[4]) return 1;
if (y==5&&!vis[5]) return 1;
if (y==6&&!vis[6]) return 1;
if (y==7&&!vis[7]) return 1;
if (y==8&&!vis[8]) if (vis[5]) return 1;
if (y==9&&!vis[9]) return 1;
}
if (x==3)
{
if (y==1&&!vis[1]) if (vis[2]) return 1;
if (y==2&&!vis[2]) return 1;
if (y==4&&!vis[4]) return 1;
if (y==5&&!vis[5]) return 1;
if (y==6&&!vis[6]) return 1;
if (y==7&&!vis[7]) if (vis[5]) return 1;
if (y==8&&!vis[8]) return 1;
if (y==9&&!vis[9]) if (vis[6]) return 1;
}
if (x==4)
{
if (y==1&&!vis[1]) return 1;
if (y==2&&!vis[2]) return 1;
if (y==3&&!vis[3]) return 1;
if (y==5&&!vis[5]) return 1;
if (y==6&&!vis[6]) if (vis[5]) return 1;
if (y==7&&!vis[7]) return 1;
if (y==8&&!vis[8]) return 1;
if (y==9&&!vis[9]) return 1;
}
if (x==5)
{
if (y==1&&!vis[1]) return 1;
if (y==2&&!vis[2]) return 1;
if (y==3&&!vis[3]) return 1;
if (y==4&&!vis[4]) return 1;
if (y==6&&!vis[6]) return 1;
if (y==7&&!vis[7]) return 1;
if (y==8&&!vis[8]) return 1;
if (y==9&&!vis[9]) return 1;
}
if (x==6)
{
if (y==1&&!vis[1]) return 1;
if (y==2&&!vis[2]) return 1;
if (y==3&&!vis[3]) return 1;
if (y==4&&!vis[4]) if (vis[5]) return 1;
if (y==5&&!vis[5]) return 1;
if (y==7&&!vis[7]) return 1;
if (y==8&&!vis[8]) return 1;
if (y==9&&!vis[9]) return 1;
}
if (x==7)
{
if (y==1&&!vis[1]) if (vis[4]) return 1;
if (y==2&&!vis[2]) return 1;
if (y==3&&!vis[3]) if (vis[5]) return 1;
if (y==4&&!vis[4]) return 1;
if (y==5&&!vis[5]) return 1;
if (y==6&&!vis[6]) return 1;
if (y==8&&!vis[8]) return 1;
if (y==9&&!vis[9]) if (vis[8]) return 1;
}
if (x==8)
{
if (y==1&&!vis[1]) return 1;
if (y==2&&!vis[2]) if (vis[5]) return 1;
if (y==3&&!vis[3]) return 1;
if (y==4&&!vis[4]) return 1;
if (y==5&&!vis[5]) return 1;
if (y==6&&!vis[6]) return 1;
if (y==7&&!vis[7]) return 1;
if (y==9&&!vis[9]) return 1;
}
if (x==9)
{
if (y==1&&!vis[1]) if (vis[5]) return 1;
if (y==2&&!vis[2]) return 1;
if (y==3&&!vis[3]) if (vis[6]) return 1;
if (y==4&&!vis[4]) return 1;
if (y==5&&!vis[5]) return 1;
if (y==6&&!vis[6]) return 1;
if (y==7&&!vis[7]) if (vis[8]) return 1;
if (y==8&&!vis[8]) return 1;
}
return 0;
}
int macth_two() //查询新图与原图是否完全匹配,匹配则说明能构造原图,反之不能
{
int i,j;
for( i=1;i<=9;i++)
for( j=1;j<=9;j++)
if(connect_map[i][j]!=given_map[i][j])
return 0;
return 1;
}
int construct(int y) //构建新图的函数
{
tmp[++cnt]=y;
vis[y]=1;
if (cnt==m) /// 把所有点已经连接完后
{
memset(connect_map,0,sizeof(connect_map));
int i;
for (i=1;i<=m;i++)
{
connect_map[tmp[i]][tmp[i-1]]=1; //
connect_map[tmp[i-1]][tmp[i]]=1; // 相邻的两个点 都在图中连接
}
create_full(); // 把新图补齐
if (macth_two()) //查询匹配
{
flag=1;
return 1;
}
else
{
vis[y]=0;
return 0;
}
}
int i;
for (i=1;i<=9;i++) //遍历map[x] vector
{
if (given_map[y][i])
{
// printf("%d\n",i);
int tm=search_legal(y,i);
if ( vis[i ] ==0 && tm==1 ) // vis[]=0 表示没遍历过该点
{
//vis[ y] =1; //标记已经遍历过,下次不再进入此边
int ans=construct(i); // 递归查找
if (ans) return 1;
cnt--; // 之前忘记了cnt-- 递归出来后要减掉
// cnt--;
}
}
}
vis[y]=0;
if (flag) return 1;
return 0;
}
int main()
{
int a,b;
int i,j,k,t,c;
scanf("%d",&t);
for (k=1;k<=t;k++)
{
for (i=0;i<=9;i++)
{
map[i].clear();
}
memset(vis_1,0,sizeof(vis_1));
memset(given_map,0,sizeof(given_map));
memset(f,0,sizeof(f));
scanf("%d",&n);
int choose;
for (i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
f[i][0]=a;
f[i][1]=b;
given_map[a][b]=1;
given_map[b][a]=1;
vis_1[a]++; //标记出现过次数
vis_1[b]++;
map[b].push_back(a);
map[a].push_back(b);
}
choose=a; //随便选一个数
linkmap();
int ans;
int cun=0,connect=0;
for (i=1;i<=9;i++)
{
memset(vis,0,sizeof(vis));
if (vis_1[i])
{
ans=query(choose,i); // 查询每一个点与别的全部数是否联通,如果是,则整个图联通,反之则否
if (ans==1) cun++;
}
}
m=0;
for (i=1;i<=9;i++)
{
if (vis_1[i]) m++; //计算总共几个点
}
if (cun==m) connect=1; //联通图
if (connect==0) //先判断是否联通
{
printf("IMPOSSIBLE\n");
continue;
}
for (i=1;i<=9;i++) //把每一个点作为开头,去搜索得到一条 合法路径,然后用该路径 构造出一个新图,与原图匹配,看是否完全匹配
{
if (vis_1[i])
{
cnt=0;
flag=0;
memset(tmp,0,sizeof(tmp));
memset(vis,0,sizeof(vis));
construct(i);
if (flag) break;
}
}
if (flag==1)
{
for (i=1;i<=m;i++)
{
printf("%d ",tmp[i]);
}
printf("\n");
continue;
}
else
{
printf("IMPOSSIBLE\n");
continue;
}
}
return 0;
}