HDU 1054 最小顶点覆盖

来源:互联网 发布:手机预约挂号软件 编辑:程序博客网 时间:2024/05/01 16:20

Strategic Game

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 910    Accepted Submission(s): 354

Problem Description
Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad. Now he has the following problem. He must defend a medieval city, the roads of which form a tree. He has to put the minimum number of soldiers on the nodes so that they can observe all the edges. Can you help him?

Your program should find the minimum number of soldiers that Bob has to put for a given tree.

The input file contains several data sets in text format. Each data set represents a tree with the following description:

the number of nodes
the description of each node in the following format
node_identifier:(number_of_roads) node_identifier1 node_identifier2 ... node_identifier
or
node_identifier:(0)

The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500). Every edge appears only once in the input data.

For example for the tree:



the solution is one soldier ( at the node 1).

The output should be printed on the standard output. For each given input data set, print one integer number in a single line that gives the result (the minimum number of soldiers). An example is given in the following table:
 

 

Sample Input
40:(1) 11:(2) 2 32:(0)3:(0)53:(3) 1 4 21:(1) 02:(0)0:(0)4:(0)
 

 

Sample Output
12
//自己实现的时候,由于申请了一个1505*1505的数组,结果超时,参考了网上的代码,但是此代码也有缺陷,由于ma只申请了每个节点后只有
//11个节点,此题能过说明测试用例不够强,不推荐此方法,见后面我自己写的代码.
24259022010-05-06 23:44:48Accepted10543859MS480K816 BC++chen

#include<stdio.h>
#include<memory.h>
int ma[1500][11];
int link[15001];
int len[15001];
bool useif[150001];
bool can(int v)
{
  for(int u=0;u<len[v];u++)
  {
    if(!useif[ma[v][u]])
    {
      useif[ma[v][u]]=1;
      if(link[ma[v][u]]==-1||(can(link[ma[v][u]])))
      {
         link[ma[v][u]]=v;
         return 1;
      }
    }
  }
  return 0;
}
int main()
{
   int x,n,i,ans,m,y,max,num;
   while(scanf("%d",&n)!=EOF)
   {
      memset(len,0,4*n);
      num=n;
      while(n--)
      {
         scanf("%d:(%d)",&x,&m);
         while(m--&&scanf("%d",&y))
         {
             ma[x][len[x]++]=y;
             ma[y][len[y]++]=x;
         }
      }
       ans=0;
       memset(link,-1,4*num);
      for(i=0;i<num;i++)
      {
          memset(useif,0,sizeof(useif));
          if(can(i))
            ans++;
      }
      printf("%d/n",ans/2);
   }
   return 0;
}

 

//经过几天的思考这种解法是很不完善的,自己就用动态邻接链表和动态临界链表重写了一遍

6868513

c00h00g

1463

Accepted

176K

641MS

C++

1505B

2010-05-08 16:53:25

//本题目对空间和时间的要求较高,若用邻接矩阵写会超时,若用动态链表写会超内存,//所以这里我们采用的是静态链表。

//这里采用的是匈牙利算法的邻接表形式

//我们要先将图补成二分图,因为12有边,21也有变,但求的结果要处以2

//由于边的个数最多为顶点的2倍,故开数组的时候要开成顶点的的2倍,否则会出现

//runtime error

#include<iostream>

using namespace std;

 

//用来表示边,to表示边的另一个定点,next用来记录下一条边的编号

struct Node

{

    int to;

    int next;

};

//用来表示定点,first用来记录顶点的第一条边的编号,1开始编号

struct ve

{

    int first;

};

 

Node edge[1505*2];

ve vex[1505];

int used[1505];

//记录当前与y节点相连的x顶点

int link[1505];

int n;

 

int can(int t)

{

    //获取此顶点的第一条边

    int temp=vex[t].first;

    while(temp!=-1)

    {

       int to=edge[temp].to;

       if(used[to]==0)

       {

           used[to]=1;

           if(link[to]==-1||can(link[to]))

           {

              link[to]=t;

              return 1;

           }

       }

       temp=edge[temp].next;

    }

    return 0;

}

 

int res()

{

    int sum=0;

    memset(link,-1,sizeof(link));

    for(int i=1;i<=n;i++)

    {

       memset(used,0,sizeof(used));

       if(can(i))

           sum++;

    }

    return sum;

}

 

void init()

{

    for(int i=1;i<=n;i++)

    {

       vex[i].first=-1;

    }

    for(int i=1;i<=2*n;i++)

    {

       edge[i].next=-1;

       edge[i].to=-1;

    }

}

 

int main()

{

    int i,j,from,num,to,count;

    while(scanf("%d",&n)!=EOF)

    {

       init();

       count=1;

       for(i=0;i<n;i++)

       {

           scanf("%d:(%d)",&from,&num);

           from++;

           while(num--)

           {

              scanf("%d",&to);

              to++;

             

              int temp=vex[from].first;

              bool flag=false;

              while(temp!=-1)

              {

                  if(edge[temp].to==to)

                  {

                     flag=true;

                     break;

                  }

                  temp=edge[temp].next;

              }

              if(!flag)

              {

                  //构建静态链表

                  edge[count].to=to;

                  edge[count].next=vex[from].first;

                  vex[from].first=count;

                  count++;

 

                  edge[count].to=from;

                  edge[count].next=vex[to].first;

                  vex[to].first=count;

                  count++;

              }

           }

       }

       printf("%d/n",res()/2);

    }

    return 0;

}

2431332

2010-05-08 17:12:24

Accepted

1054

296MS

9692K

1044 B

C++

chen

#include<iostream>

using namespace std;

 

struct Node

{

    int to;

    Node* next;

};

int used[1515];

Node* edge[1515];

int link[1515];

int n;

//对于左边每个顶点

bool can(int t)

{

    for(Node* temp=edge[t];temp;temp=temp->next)

    {

       int v=temp->to;

       if(used[v]==0)

       {

           used[v]=1;

           if(link[v]==-1||can(link[v]))

           {

              link[v]=t;

              return 1;

           }

       }

    }

    return 0;

}

 

int MaxMatch()

{

    int num=0;

    memset(link,-1,sizeof(link));

    for(int i=1;i<=n;i++)

    {

       memset(used,0,sizeof(used));

       if(can(i))

           num++;

    }

    return num;

}

 

int main()

{

    int i,j,from,num,to;

    while(scanf("%d",&n)!=EOF)

    {

       for(i=0;i<n;i++)

       {

           scanf("%d:(%d)",&from,&num);

           from++;

           while(num--)

           {

              scanf("%d",&to);

              to++;

              Node* temp=new Node;

              temp->to=to;

              temp->next=edge[from];

              edge[from]=temp;

 

              Node* tmp=new Node;

              tmp->to=from;

              tmp->next=edge[to];

              edge[to]=tmp;

           }

       }

       printf("%d/n",MaxMatch()/2);

              for(i=1;i<=n;i++)

           edge[i]=NULL;

    }

}