转载:http://hi.baidu.com/zyz913614263/item/7ef07c5c52200305da163576
今天第一次写欧拉回路的题,虽说之前看过此类算法,但是实践起来还是有区别的。
求欧拉回路的一种解法
下面是无向图的欧拉回路输出代码:注意输出的前提是已经判断图确实是欧拉回路。
int num = 0;//标记输出队列
int match[MAX];//标志节点的度,无向图,不区分入度和出度
void solve(int x)
{
if(match[x] == 0)
record[num++] = x;
else
{
for(int k =1;k<=n;k++)
{
if(vis[x][k] !=0 )
{
vis[x][k]--;
vis[k][x]--;
match[x]--;
match[k]--;
solve(k);
}
}
record[num++] = x;
}
}
注意record中的点的排列是输出的到序,因此,如果要输出欧拉路径,需要将record倒过来输出。(跟DFS一样,不解释了)
求欧拉回路的思路:
循环的找到出发点。从某个节点开始,然后查出一个从这个出发回到这个点的环路径。这种方法保证每个边都被遍历。如果有某个点的边没有被遍历就让这个点为起点,这条边为起始边,把它和当前的环衔接上。这样直至所有的边都被遍历。这样,整个图就被连接到一起了。<其实就是DFS遍历图,没什么区别>
具体步骤:
1。如果此时与该点无相连的点,那么就加入路径中;
2。如果该点有相连的点,那就列一张表,遍历这些点,知道没有相连的点。
3。处理当前的点,删除走过的这条边,并在其相邻的点上进行同样的操作,并把删除的点加入到路径中去。
4。这个其实是个递归过程。<DFS求解>
对于这题一条边的两个端点,作为两个点(0~6)见一个最多六个点的图,然后打印欧拉回路
最后,判断是输入中的哪条边就可以了。
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 12;
const int maxm = 120;
int vis[maxn][maxn],used[maxn];
int match[maxn],f[maxn],num,n;
//int num = 0;//标记输出队列
//int match[MAX];//标志节点的度,无向图,不区分入度和出度
struct node{
int x,y;
}p[maxm];
int record[maxm];
int cnt[maxm];
void dfs(int v)
{
for(int i=0;i<=6;i++) // 0~6
if(vis[v][i]&&!used[i])
{
used[i]=1;
dfs(i);
}
}
void solve(int x)
{
if(match[x]==0) record[num++]=x;
else
{
for(int k=0;k<=6;k++) // 0 ~ 6
{
if(vis[x][k]!=0)
//if(vis[x][k]>0)
{
vis[x][k]--;
vis[k][x]--;
match[x]--;
match[k]--;
solve(k);
}
}
record[num++]=x;
}
}
int main()
{
scanf("%d",&n);
memset(match,0,sizeof(match));
memset(vis,0,sizeof(vis));
memset(f,0,sizeof(f));
for(int i=0;i<n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
match[p[i].x]++;
match[p[i].y]++;
vis[p[i].x][p[i].y]++;
vis[p[i].y][p[i].x]++;
f[p[i].x]=1;
f[p[i].y]=1;
}
used[p[0].x]=1;
dfs(p[0].x);
for(int i=0;i<=6;i++)
if(!used[i]&&f[i])
{
printf("No solution\n");
return 0;
}
int s=0,flag=-1;
for(int i=0;i<=6;i++)
if(match[i]%2&&f[i])
{
s++;
flag=i;
}
if(s==1||s>=3)
{
printf("No solution\n");
return 0;
}
num=0;
if(s==2)
{
solve(flag);
}
else solve(p[0].x);
memset(cnt,0,sizeof(cnt));
for(int i=0;i<num-1;i++)
{
for(int j=0;j<n;j++)
if(p[j].x==record[i]&&p[j].y==record[i+1]&&!cnt[j])
{
cnt[j]=1;
printf("%d +\n",j+1);
break;
}
else if(p[j].y==record[i]&&p[j].x==record[i+1]&&!cnt[j])
{
cnt[j]=1;
printf("%d -\n",j+1);
break;
}
}
return 0;
}