zoukankan      html  css  js  c++  java
  • POJ 1469 COURSES (二分匹配,邻接表)

    http://poj.org/problem?id=1469

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<iostream>
      4 #define point_MAX 10000
      5 #define edge_MAX 100000
      6 using namespace std;
      7 struct EDGE
      8 {
      9     int to;/*指向的点*/
     10     int next;/*指向的下一条邻边*/
     11     int w;/*权值*/
     12 }edge[edge_MAX];
     13 int len;/*边的数量*/
     14 int point[point_MAX];
     15 int nx,ny;/*x集合和y集合中顶点的个数*/
     16 int cx[point_MAX],cy[point_MAX];/*用来记录x集合中匹配的y元素是哪个!*/
     17 int visited[point_MAX];/*用来记录该顶点是否被访问过!*/
     18 void init()/*初始化*/
     19 {
     20     len=0;
     21     memset(point,0,sizeof(point));
     22 }
     23 int add_edge(int a,int b,int w)/*添加由a指向b的权值为w的边*/
     24 {
     25     int i;
     26     for(i=point[a];i;i=edge[i].next)
     27     {
     28         if(edge[i].to==b)
     29            {
     30             if(edge[i].w<w)/*重边取大*/
     31             {
     32                 edge[i].w=w;
     33                 return 1;/*有重边,并覆盖*/
     34             }
     35             return -1;/*有重边舍去*/
     36            }
     37     }
     38     /*以上处理重边*/
     39     len++;
     40     edge[len].w=w;
     41     edge[len].to=b;
     42     edge[len].next=point[a];
     43     point[a]=len;
     44     return 0;/*无重边,插入*/
     45 }
     46  int path(int u)/*由点u开始寻找增广路,即将u与刚刚的连线去掉,继而寻找新的连线*/
     47  {
     48      int v;
     49      for(v=point[u];v;v=edge[v].next)
     50      {
     51          if(!visited[edge[v].to])/*找到的这个必须之前没有找过的点,就是在不与其他点冲突的情况下寻找增广路*/
     52          {
     53              visited[edge[v].to]=1;
     54             if(cy[edge[v].to]==-1||path(cy[edge[v].to]))/*如果y集合中的v元素没有匹配或者是v已经匹配,但是从cy[v]中能够找到一条增广路*/
     55              {
     56                  /*cx[u]=edge[v].to;这是无向图中才要的*/
     57                  cy[edge[v].to]=u;
     58                  return 1;
     59              }
     60          }
     61      }
     62      return 0;
     63  }
     64  int maxmatch()/*遍历所有的点,不断寻找增广路,直到结束*/
     65  {
     66      int res=0,i;
     67      for(i=0;i<point_MAX;i++)
     68         cx[i]=cy[i]=-1;/*初始值为-1表示两个集合中都没有匹配的元素!*/
     69      for(i=0;i<=nx;i++)
     70      {
     71          if(cx[i]==-1)
     72          {
     73              memset(visited,0,sizeof(visited));
     74              res+=path(i);/*寻找增广路*/
     75          }
     76      }
     77      return res;
     78  }
     79 int main()
     80  {
     81      int i,n,j,x,y,ans,t;
     82      cin>>t;
     83      while(t--)
     84      {
     85          scanf("%d%d",&nx,&ny);//nx-->course,ny-->student
     86          //ny=nx;
     87          init();/*初始化*/
     88          for(i=0;i<nx;i++)
     89          {
     90             scanf("%d",&n);
     91             for(j=0;j<n;j++)
     92             {
     93                 scanf("%d",&y);
     94                 add_edge(i+1,y,1);
     95             }
     96          }
     97          ans=maxmatch();/*匈牙利算法*/
     98          /*for(i=0;i<ny;i++)
     99          {
    100              if(cy[i]==-1)break;
    101          }*/
    102          if(ans==nx)
    103          printf("YES
    ");
    104          else cout<<"NO"<<endl;
    105      }
    106      return 0;
    107  }
    View Code

    模板里的数从0开始。

    匈牙利算法每次寻找增广路的结束条件是能够递归找到y集合中的点没有被x集合中的点连接的。此时即可返回1.表示可增广。

  • 相关阅读:
    January 25th, 2018 Week 04th Thursday
    January 24th, 2018 Week 04th Wednesday
    January 23rd, 2018 Week 04th Tuesday
    January 22nd, 2018 Week 04th Monday
    January 21st, 2018 Week 3rd Sunday
    January 20th, 2018 Week 3rd Saturday
    January 19th, 2018 Week 3rd Friday
    January 18th, 2018 Week 03rd Thursday
    January 17th, 2018 Week 03rd Wednesday
    January 16th, 2018 Week 03rd Tuesday
  • 原文地址:https://www.cnblogs.com/huzhenbo113/p/3683864.html
Copyright © 2011-2022 走看看