二部图实现的简单例子源码

问题 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;
}
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值