• hdu 2444 The Accomodation of Students(二分匹配 匈牙利算法 邻接表实现)


    The Accomodation of Students

    Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 3565    Accepted Submission(s): 1659


    Problem Description
    There are a group of students. Some of them may know each other, while others don't. For example, A and B know each other, B and C know each other. But this may not imply that A and C know each other.

    Now you are given all pairs of students who know each other. Your task is to divide the students into two groups so that any two students in the same group don't know each other.If this goal can be achieved, then arrange them into double rooms. Remember, only paris appearing in the previous given set can live in the same room, which means only known students can live in the same room.

    Calculate the maximum number of pairs that can be arranged into these double rooms.
     
    Input
    For each data set:
    The first line gives two integers, n and m(1<n<=200), indicating there are n students and m pairs of students who know each other. The next m lines give such pairs.

    Proceed to the end of file.

     
    Output
    If these students cannot be divided into two groups, print "No". Otherwise, print the maximum number of pairs that can be arranged in those rooms.
     
    Sample Input
    4 4
    1 2
    1 3
    1 4
    2 3
    6 5
    1 2
    1 3
    1 4
    2 5
    3 6
     
    Sample Output
    No
    3
     
    Source

    题意: 有n个人,m条关系,问通过这些关系判断,所有人是否可以分成两个组,如果可以則求出一组最多多少人。

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <math.h>
      5 #include <iostream>
      6 #include <algorithm>
      7 #include <climits>
      8 #include <queue>
      9 #define ll long long
     10 
     11 using namespace std;
     12 
     13 const int N = 20000;
     14 int head[N],total,visit[N];
     15 int link[N],color[250];
     16 
     17 struct nodes
     18 {
     19     int e,next;
     20 } Edge[N];
     21 
     22 
     23 void add(int x,int y)//加边,邻接表形式建图
     24 {
     25     Edge[total].e = y;
     26     Edge[total].next = head[x];
     27     head[x] = total++;
     28 }
     29 
     30 int dfs(int f) //匈牙利算法中的二分匹配dfs实现
     31 {
     32     for(int i  = head[f]; i != -1; i = Edge[i].next)//邻接表遍历与起始点f相连的所有点
     33     {
     34         int s = Edge[i].e; //与起始点相连的点
     35         if(visit[s]) continue;//访问过就跳过
     36         visit[s] = 1;
     37         if(link[s] == -1 || dfs(link[s]))//寻找增广路径
     38         {
     39             link[s] = f ;
     40             return 1;
     41         }
     42     }
     43     return 0;
     44 }
     45 
     46 void init()//初始化
     47 {
     48     total = 0;
     49     memset(head,-1,sizeof(head));
     50     memset(link,-1,sizeof(link));
     51 }
     52 bool bcolor(int u,int x)
     53 {
     54     if(color[u] != -1)//如果从上个点出发过来,发现该点已染色
     55     {
     56         if(color[u] == x)//如果此点颜色与邻点相同
     57             return false; //不是二分图,返回染色失败
     58     }
     59     else
     60     {
     61         color[u] = x^1;//该点未染色,則染与上个点不同的颜色
     62         for(int i = head[u]; i != -1; i = Edge[i].next)//遍历与该点相连的所有边
     63         {
     64             if(!bcolor(Edge[i].e,color[u]))//如果下一层染色失败,則返回失败
     65                 return false;
     66         }
     67     }
     68     return true;
     69 }
     70 bool judge(int n)
     71 {
     72     memset(color,-1,sizeof(color));//先初始化所有点为-1,代表未染色
     73     for(int i = 1; i <= n; i++)//依次检查点是否染过色
     74     {
     75         if(color[i] == -1)//若没访问过,則开始填色
     76         {
     77             if(!bcolor(i,0))
     78                 return false;
     79         }
     80     }
     81     return true;
     82 }
     83 int main(void)
     84 {
     85     int n,i,cnt,m;
     86     while(scanf("%d",&n) != -1)
     87     {
     88         init();
     89         scanf("%d",&m);
     90         for(i = 0; i < m; i++)
     91         {
     92             int x,y;
     93             scanf("%d %d",&x,&y);
     94             add(x,y);
     95             //add(y,x);
     96         }
     97         if(!judge(n)) // 判断是否为二分图
     98         {
     99             printf("No
    ");
    100         }
    101         else //匈牙利算法
    102         {
    103             for(cnt = 0,i = 1; i <= n; i++)
    104             {
    105                 memset(visit,0,sizeof(visit));
    106                 if(dfs(i))
    107                     cnt++;
    108             }
    109             printf("%d
    ",cnt);//若建的双向边則最大匹配数统计了两次,因为是双向的,所以需除以2 ;若建的单向边,則不需要除以2.
    110         }
    111 
    112     }
    113     return 0;
    114 }
  • 相关阅读:
    (五)L-BFGS算法
    (四)BFGS
    (三)DFP算法
    (二)拟牛顿条件
    (一)牛顿法与阻尼牛顿法
    遗传算法求解最优值
    Anaconda(Python3.6)配置OpenCV3.3
    SVM基础知识
    IO流
    webserver服务器优化0.1
  • 原文地址:https://www.cnblogs.com/henserlinda/p/4717475.html
Copyright © 2020-2023  润新知