题目描述
让我们想象一个无向图G=<V,E>.如果边(u,v)在边集E中,那么我们就说两个顶点u和v是邻接点.在这种情况下,我们也说u是v的一个邻接点且v是u的一个邻接点.我们用N(v)表示点v的邻接点集
合.我们知道v的邻接点数目也叫作这个点的度,用deg v表示.
我们说图G是奇怪的如果它是连通的且对于它的每一个点满足如下条件:
1.点v的度deg v>=2(表明v的邻接点至少有两个)
2.如果点v的度deg v=2,那么它的两个邻接点之间没有边相连
3.如果点v的度deg v>2,那么在它的邻接点集合N(v)中存在点u满足:
(a)点u的度deg u=2
(b)集合N(v)中除顶点u外任意两个不同的点是相邻的,即(w1,w2)这条边存在于边集E中.
现在给你某个这样的图,在里面找出一条哈密尔顿回路,一条哈密尔顿回路就是一条回路,这条回路经过图G中的每一点,且只经过一次.
输入
输入文件的第一行包含两个整数N和M——N为图G中定点的数目,M为图G中边的数目
(3<=N<=10000,M<=100000).接下来为2M个整数(每相邻两个点为一对)——每对数代表一条边的两个顶点(顶点被编号为1-N).输入数据保证每条边仅出现一次,且没有这样的环(边的两端点相同).
输出
如果在图G中没有哈密尔顿回路,则在输出文件的第一行输出-1.如果存在,则输出N个数——即在图G中找到的哈密尔顿回路的顶点序列(注意:最后一个点必须与第一个点相连).
如果有多种解,则输出任意一种即可.
Sample input #1
4 4
1 2 2 3 3 4 4 1
Sample input #2
9 12
1 2 2 3 3 1 1 4 2 5 3 6
4 7 5 8 6 9 7 8 8 9 9 7
Sample output #1
1 2 3 4
Sample output #2
-1
分析:
根据题意,很明显由条件3(b)我们可得一个deg>2的点与它所连的除deg=2的点可构成一个可两两相邻的连通分量,由此我们可以将其缩点。
然而求解哈密尔顿回路在此可以转换成在新图中求解欧拉回路,因为根据3(b),两个连通分量之间只可能由deg=2的一些点连接,且每个连通分量中的点都唯一对应一个deg=2的结点。
也就是说在新图中每走过一条边,就是走过了一个点,得证。
细节注意下哈,这题还是不难写的。
让我们想象一个无向图G=<V,E>.如果边(u,v)在边集E中,那么我们就说两个顶点u和v是邻接点.在这种情况下,我们也说u是v的一个邻接点且v是u的一个邻接点.我们用N(v)表示点v的邻接点集
合.我们知道v的邻接点数目也叫作这个点的度,用deg v表示.
我们说图G是奇怪的如果它是连通的且对于它的每一个点满足如下条件:
1.点v的度deg v>=2(表明v的邻接点至少有两个)
2.如果点v的度deg v=2,那么它的两个邻接点之间没有边相连
3.如果点v的度deg v>2,那么在它的邻接点集合N(v)中存在点u满足:
(a)点u的度deg u=2
(b)集合N(v)中除顶点u外任意两个不同的点是相邻的,即(w1,w2)这条边存在于边集E中.
现在给你某个这样的图,在里面找出一条哈密尔顿回路,一条哈密尔顿回路就是一条回路,这条回路经过图G中的每一点,且只经过一次.
输入
输入文件的第一行包含两个整数N和M——N为图G中定点的数目,M为图G中边的数目
(3<=N<=10000,M<=100000).接下来为2M个整数(每相邻两个点为一对)——每对数代表一条边的两个顶点(顶点被编号为1-N).输入数据保证每条边仅出现一次,且没有这样的环(边的两端点相同).
输出
如果在图G中没有哈密尔顿回路,则在输出文件的第一行输出-1.如果存在,则输出N个数——即在图G中找到的哈密尔顿回路的顶点序列(注意:最后一个点必须与第一个点相连).
如果有多种解,则输出任意一种即可.
Sample input #1
4 4
1 2 2 3 3 4 4 1
Sample input #2
9 12
1 2 2 3 3 1 1 4 2 5 3 6
4 7 5 8 6 9 7 8 8 9 9 7
Sample output #1
1 2 3 4
Sample output #2
-1
分析:
根据题意,很明显由条件3(b)我们可得一个deg>2的点与它所连的除deg=2的点可构成一个可两两相邻的连通分量,由此我们可以将其缩点。
然而求解哈密尔顿回路在此可以转换成在新图中求解欧拉回路,因为根据3(b),两个连通分量之间只可能由deg=2的一些点连接,且每个连通分量中的点都唯一对应一个deg=2的结点。
也就是说在新图中每走过一条边,就是走过了一个点,得证。
细节注意下哈,这题还是不难写的。
#include <cstdio>
#include <cstdlib>
using namespace std;
const int MAXN = 10005, MAXM = 100005;
int n, m;
struct edge
{
int node;
edge *nxt;
}*e[MAXN] = {NULL}, *t[MAXN] = {NULL};
int deg[MAXN] = {0}, _deg[MAXN] = {0};
int col[MAXN] = {0}, top = 0;
int vis[MAXN] = {0}, s = 0;
bool hash[MAXN] = {0};
void add(int u, int v)
{
edge *tmp;
tmp = (edge *)malloc(sizeof(edge));
tmp->node = v;
tmp->nxt = NULL;
if(e[u] == NULL)
e[u] = t[u] = tmp;
else
{
t[u]->nxt = tmp;
t[u] = tmp;
}
}
void dfs(int cur, int src)
{
hash[cur] = true;
for(edge *i = e[cur]; i != NULL; i = i->nxt)
if(!hash[i->node])
{
int to = i->node;
if(src && col[cur] == col[to])
dfs(to, 0);
else if((!src && col[cur] != col[to]) || deg[cur] == 2)
dfs(to, 1);
}
vis[++s] = cur;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i)
{
int x, y;
scanf("%d%d", &x, &y);
add(x, y);add(y, x);
deg[x]++;deg[y]++;
}
for(int i = 1; i <= n; ++i)
if(deg[i] > 2 && !col[i])
{
++top;
col[i] = top;
for(edge *j = e[i]; j != NULL; j = j->nxt)
if(deg[j->node] > 2)
col[j->node] = top;
}
else if(deg[i] == 2)
col[i] = ++top;
for(int i = n; i >= 1; --i)
if(deg[i]&1)//因为一个点的deg就代表了这个分量的deg
{
puts("-1");
return 0;
}
dfs(1, 0);
for(int i = 1; i <= s; ++i)
printf("%d ", vis[i]);
return 0;
}