您的位置:首页 > Web前端

Riding the Fences

2013-10-28 19:48 253 查看
题意:有F个栅栏,每个栅栏连接编号分别为x、y(均在[1, 500]内)的点,求最小欧拉回路。回路用编号序列代表,最小的定义:用500进制表示回路编号的序列是最小的。

解题思路

典型的求欧拉回路的问题
用邻接表adj_table[i][j]来表示这张图。adj_table[i][0] = k表示点i有k个邻节点,那么adj_table[i][1...k]就代表了这k个邻节点的编号
参考(http://cerberus.delos.com:791/usacotext2?a=bhJRyLLAHTZ&S=euler)下面的求欧拉回路的过程,编写生成以节点location为起点的回路的函数FindCircuit(location)
FindCircuit(location),首先初始化一个栈stack和用来保存回路的数组circuit,并用两个变量stack_top和circuit_pos来维护两者
如果location没有邻节点,那么location就是新找到的回路节点,存到circuit中。然后将栈顶的元素取出作为新的location,如果栈空则执行完毕。如果location有邻节点,将location放到栈中,然后取出其最小的邻节点作为新的location,并将连接二者的边从邻接表中删去
循环执行5,直至栈空,那么就找到了以location为起点的欧拉回路
因为所给的输入都有欧拉回路。首先寻找第一个度是奇数的点为location,如果均为偶数,则度不为0的第一个点为location。然后执行FindCircuit(location)即可得到输出
代码

/*
ID: zc.rene1
LANG: C
PROG: fence
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAX_NODES 500

int F;
int adj_table[MAX_NODES + 1][MAX_NODES + 1];

int FindLeast(int location)
{
int min = MAX_NODES + 1, min_i = -1;
int len = adj_table[location][0];
int i = 1, j, count = 0;

while (count < len)
{
if (adj_table[location][i] == -1)
{
i++;
continue;
}
else
{
count++;
if (adj_table[location][i] < min)
{
min = adj_table[location][i];
min_i = i;
}
i++;
}
}
j = adj_table[location][min_i];
adj_table[location][min_i] = -1;
adj_table[location][0]--;

i = 1;
while (adj_table[j][i] != location)
{
i++;
}
adj_table[j][0]--;
adj_table[j][i] = -1;

return min;
}

void FindCircuit(int location, FILE *fout)
{
int *stack = (int *)malloc((F + 1) * sizeof(int));
int *circuit = (int *)malloc((F + 1) * sizeof(int));
int circuit_pos = 0, stack_top = -1;

memset(stack, 0, (F + 1) * sizeof(int));
memset(circuit, 0, (F + 1) * sizeof(int));

while (1)
{
if (adj_table[location][0] == 0)
{
circuit[circuit_pos++] = location;
if (stack_top == -1)
{
break ;
}
else
{
location = stack[stack_top--];
}
}
else
{
stack[++stack_top] = location;
location = FindLeast(location);
}
}

int i;
for (i=circuit_pos-1; i>=0; i--)
{
fprintf(fout, "%d\n", circuit[i]);
}
}

int main(void)
{
FILE *fin, *fout;
int i, j, k;

fin = fopen("fence.in", "r");
fout = fopen("fence.out", "w");

/*get the input*/
memset(adj_table, 0, (MAX_NODES + 1) * (MAX_NODES + 1) * sizeof(int));
fscanf(fin, "%d", &F);
for (i=0; i<F; i++)
{
fscanf(fin, "%d %d", &j, &k);
adj_table[j][0]++;
adj_table[j][adj_table[j][0]] = k;
adj_table[k][0]++;
adj_table[k][adj_table[k][0]] = j;
}
/*start to find Eulerian Tours*/
for (i=1; i<=MAX_NODES; i++)
{
if (adj_table[i][0] % 2 == 1)
{
FindCircuit(i, fout);
break;
}
}
if (i > MAX_NODES)
{
for (i=1; i<=MAX_NODES; i++)
{
if (adj_table[i][0] != 0)
{
FindCircuit(i, fout);
break;
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: