问题 google code jam 上的一个简单的问题
http://code.google.com/codejam/contest/635101/dashboard#s=p0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNAMELENGTH 100
#define MAXEDGES 100
typedef struct inner_node{
int id;
inner_node * next;
}i_node;
typedef struct node
{
int id;
char name[MAXNAMELENGTH];
char color; // color = 'w' represent white; and color = 'b' represent black; color = 'e' represent empty.
i_node * head;
i_node * tail;
}g_node;
typedef struct graph{
g_node * v_array[MAXEDGES * 2];
int size;
i_node * q_head;
i_node * q_tail;
}p_graph;
//g_node * v_array[MAXEDGES * 2];
void init_graph(p_graph *g);
g_node * get_empty_node();
i_node * get_empty_inode();
p_graph * create_bipartite_graph();
int is_node_exist(p_graph * g, char * v_name);
int is_conflict(p_graph *g, int id1, int id2);
int is_edge_exist(p_graph * g, char * v_name1, char * v_name2);
i_node * get_empty_inode()
{
i_node * result = NULL;
result = (inner_node *) malloc(sizeof(inner_node));
result->id = -1;
result->next = NULL;
return result;
}
/*
* judge the edge which named with v_name1 and v_name2, whether exist
* return: 1 represent exist, -1 represent not-exist
*/
int is_edge_exist(p_graph * g, char * v_name1, char * v_name2)
{
i_node * t_node = NULL;
int id1 = -1, id2 = -1;
id1 = is_node_exist(g, v_name1);
id2 = is_node_exist(g, v_name2);
if(id1<0 || id2<0)
return -1; // the edge donot exist
else
{
t_node = g->v_array[id1]->head;
while(t_node != NULL)
{
if(t_node->id == id2)
return 1; // find the edge
t_node = t_node->next;
}
return -1; // the edge donot exist
}
}
/*
* return: if v_name is exist return corresponding index, otherwise return -1;
*/
int is_node_exist(p_graph * g, char * v_name)
{
int i;
for(i=0; i<g->size; ++i)
{
if(strcmp(v_name, g->v_array[i]->name) == 0)
{
return i;
}
}
return -1;
}
/*
* judge the two node whether conflict, if the two nodes have the same color then they are conflicted.
* return: 1 represent conflict; 0 reprsent not-conflicted
*/
int is_conflict(p_graph * g, int id1, int id2)
{
if(g->v_array[id1]->color != 'e' && g->v_array[id1]->color == g->v_array[id2]->color)
return 1;
else return 0;
}
void insert_list(p_graph * g, int id, i_node * n)
{
if(g==NULL || id <0 || n==NULL)
{
printf("insert list error!\n");
}
if(g->v_array[id]->head == NULL && g->v_array[id]->tail == NULL)
{
g->v_array[id]->head = n;
g->v_array[id]->tail = n;
}
else
{
g->v_array[id]->tail->next = n;
g->v_array[id]->tail = n;
}
}
void add(p_graph * g, int id1, int id2)
{
i_node * inter1 = NULL;
i_node * inter2 = NULL;
inter1 = get_empty_inode();
inter1->id = id1;
inter2 = get_empty_inode();
inter2->id = id2;
insert_list(g, id1, inter2);
insert_list(g, id2, inter1);
}
/*
*
*
*/
int insert_edge(p_graph * g, char * v_name1, char * v_name2)
{
g_node * v1 = NULL;
g_node * v2 = NULL;
i_node * inter1 = NULL;
i_node * inter2 = NULL;
int id1 = -1, id2 = -1;
id1 = is_node_exist(g, v_name1);
id2 = is_node_exist(g, v_name2);
v1 = get_empty_node();
v1->id = id1;
strcpy(v1->name, v_name1);
v2 = get_empty_node();
v2->id = id2;
strcpy(v2->name, v_name2);
if(id1 >= 0 && id2 >= 0) //case 1: the two nodes is already exist.
{
if(is_edge_exist(g, v_name1, v_name2) == -1)
{
add(g, id1, id2);
}
}
else if(id1>=0 && id2<0) //case 2: one node is exist, but another is not.
{
v2->id = g->size;
g->size ++;
strcpy(v2->name, v_name2);
g->v_array[v2->id] = v2;
add(g, id1, v2->id);
}
else if(id1<0 && id2>=0) //case 3: one node is exist, but another is not.
{
v1->id = g->size;
g->size ++;
strcpy(v1->name, v_name1);
g->v_array[v1->id] = v1;
add(g, v1->id, id2);
}
else //case 4: two nodes are both not existed.
{
v1->id = g->size;
g->size ++;
strcpy(v1->name, v_name1);
g->v_array[v1->id] = v1;
v2->id = g->size;
g->size ++;
strcpy(v2->name, v_name2);
g->v_array[v2->id] = v2;
add(g, v1->id, v2->id);
}
return 1;
}
/*
* color for id's child list with the given color.
* Note: if some nodes in the child list already have color, then we need to judge wether they are conflicted.
*
*/
int color_list(p_graph *g, int id, char color)
{
i_node * t_inner=NULL;
t_inner = g->v_array[id]->head;
while(t_inner != NULL)
{
if(g->v_array[t_inner->id]->color == 'e')
{
g->v_array[t_inner->id]->color = color;
}
else if(is_conflict(g, id, t_inner->id) == 1)
{
return -1;
}
t_inner = t_inner->next;
}
return 1;
}
i_node * copy_inode(i_node * n)
{
i_node * result = NULL;
result = (inner_node *) malloc(sizeof(inner_node));
result->id = n->id;
result->next = NULL;
return result;
}
/*
* insert a list into queue
* Note: queue and graph should point the respective i_node data. You must be careful when you want to add a node into the queue.
* And only not-colored node can be insert into queue.
*/
void insert_queue(p_graph *g, int id)
{
i_node * head = g->v_array[id]->head;
i_node * tail = g->v_array[id]->tail;
i_node * t_node = NULL;
t_node = head;
while(t_node != NULL)
{
if(g->v_array[t_node->id]->color == 'e')
{
if(g->q_head == NULL && g->q_tail == NULL) // be careful with the head and tail, especially the head is NULL.
{
g->q_head = copy_inode(head);
g->q_tail = g->q_head;
}
else
{
g->q_tail->next = copy_inode(t_node);
g->q_tail = g->q_tail->next;
}
}
t_node = t_node->next;
}
}
i_node * get_from_queue(p_graph *g)
{
i_node * result = NULL;
if(g->q_head == NULL)
{
//printf("get_from_queue: queue is empty!\n");
return NULL;
}
result = g->q_head;
g->q_head = g->q_head->next;
if(g->q_head == NULL)
{
g->q_tail = NULL;
}
return result;
}
int coloring(p_graph *g)
{
int result = 0;
i_node * t_node = NULL;
g->v_array[0]->color = 'b';
insert_queue(g, 0);
result = color_list(g, 0, 'w');
if(result == -1)
{
//printf("coloring fail!\n");
return -1;
}
while((t_node = get_from_queue(g)) != NULL)
{
//printf(" %d \n", t_node->id);
insert_queue(g, t_node->id);
if(g->v_array[t_node->id]->color == 'b')
{
result = color_list(g, t_node->id, 'w');
}
else if(g->v_array[t_node->id]->color == 'w')
{
result = color_list(g, t_node->id, 'b');
}
if(result == -1)
{
//printf("coloring failed!\n");
return -1;
}
free(t_node);
}
return 1;
}
p_graph * create_bipartite_graph()
{
p_graph * result = (graph *)malloc(sizeof(graph));
init_graph(result);
return result;
}
g_node * get_empty_node()
{
g_node * result = (node *) malloc(sizeof(node));
result->id = -1;
memset(result->name, 0, MAXNAMELENGTH);
result->color = 'e';
result->head = NULL;
result->tail = NULL;
return result;
}
void init_graph(p_graph *g)
{
int i;
for(i=0; i<MAXEDGES*2; ++i)
{
g->v_array[i] = NULL;
}
g->size = 0;
g->q_head = NULL;
g->q_tail = NULL;
}
/*
int main()
{
FILE * in = fopen("A-small-practice-2.in", "rb");
FILE * out = fopen("graph_result", "w+");
int i, j;
int result = -1;
int cases = 0;
int edges = 0;
char str[4];
char name1[100], name2[100];
fscanf(in, " %s ", str);
cases = atoi(str);
for(i=0; i<cases; ++i)
{
p_graph *g = create_bipartite_graph();
fscanf(in, " %s ", str);
edges = atoi(str);
for(j=0; j<edges; ++j)
{
fscanf(in, " %s %s ", name1, name2);
insert_edge(g, name1, name2);
}
result = coloring(g);
if(result == 1)
{
fprintf(out, "Case #%d: Yes\n", i+1);
printf("Case #%d: Yes\n", i+1);
}
else
{
fprintf(out, "Case #%d: No\n", i+1);
printf("Case #%d: No\n", i+1);
}
free(g);
}
return 1;
}
*/