HDU1068 最大独立点集

Girls and Boys

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


Problem Description
the second year of the university somebody started a study on the romantic relations between the students. The relation “romantically involved” is defined between one girl and one boy. For the study reasons it is necessary to find out the maximum set satisfying the condition: there are no two students in the set who have been “romantically involved”. The result of the program is the number of students in such a set.

The input contains several data sets in text format. Each data set represents one set of subjects of the study, with the following description:

the number of students
the description of each student, in the following format
student_identifier:(number_of_romantic_relations) student_identifier1 student_identifier2 student_identifier3 ...
or
student_identifier:(0)

The student_identifier is an integer number between 0 and n-1, for n subjects.
For each given data set, the program should write to standard output a line containing the result.
 
Sample Input
7 0: (3) 4 5 6 1: (2) 4 6 2: (0) 3: (0) 4: (2) 0 1 5: (1) 0 6: (2) 0 1 3 0: (2) 1 2 1: (1) 0 2: (1) 0
 
Sample Output
5 2
 
Source
 
Recommend
JGShining   |   We have carefully selected several similar problems for you:  1281 1507 1528 1054 2063
 
 
 
/*
题意:n个同学,一些男女同学会有缘分成为情侣,格式ni:(m) n1 n2 n3表示同学ni有缘与n1,n2,n3成为情侣,求集合中不存在有缘成为情侣的同学的最大同学数。
题解:
独立集:图的顶点集的子集,其中任意两点不相邻
最大独立集 = 顶点数 - 最大匹配数
由于本题是从整个点集搜索,并不是将点集分开成(A)(B),(1->2)(2->1)对称存在,所以相当于搜索了两遍。因此真正最大匹配数等于最大匹配数/2.
具体我也不明白其中的原理,只是理解。
*/
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 500;
bool vis[maxn];     //查询右集合中的点有没有被访问过
int link[maxn];     //link[i]表示右集合中的i点是由左集合中的哪个点连接的
int G[maxn][maxn];     //邻接矩阵
int tx,ty;          //左右集合的点的个数
bool find(int u)         //用来寻找增广路
{
    for(int i = 0; i < ty; i++)   //遍历右集合中的每个点
    {
        if(!vis[i] && G[u][i])    //没有被访问过并且和u点有边相连
        {
            vis[i] = true;  //标记该点
            if(link[i] == -1 || find(link[i]))
            {
                //该点是增广路的末端或者是通过这个点可以找到一条增广路
                link[i] = u;//更新增广路   奇偶倒置
                return true;//表示找到一条增广路
            }
        }
    }
    return false;
}

int solve()
{
    int num1 = 0;
    memset(link, -1, sizeof(link));//初始化为-1表示  不与左集合中的任何元素有link
    for(int i = 0; i < tx; i++)  //遍历左集合
    {
        memset(vis, false, sizeof(vis));//每一次都需要清除标记
        if(find(i))
            num1++;//找到一条增广路便num++
    }
    return num1;
}
int main()
{
    int a,b,c;
    int cases;
    while(scanf("%d",&cases)!=EOF)
    {
        tx=cases;
        ty=cases;
        memset(G,0,sizeof(G));
         while(cases--)
        {
           scanf("%d: (%d)",&a,&b);
           for(int i=0;i<b;i++)
           {
               scanf("%d",&c);
               G[a][c]=1;
           }
        }
       printf("%d
",tx-solve()/2);
    }
    return 0;
}
/*int main()
{

    int z1,zn,p;
    while(scanf("%d",&x_cnt)!=EOF)
    {
        y_cnt=x_cnt;
        int tt=x_cnt;
        memset(G,0,sizeof(G));

        while(tt--)
        {
            scanf("%d: (%d)",&z1,&zn);
            for(int j=1; j<=zn; j++)
            {
                scanf("%d",&p);
                G[z1][p]=1;
            }

            printf("%d
",x_cnt-solve()/2);
        }

    }
    return 0;
}*/
原文地址:https://www.cnblogs.com/13224ACMer/p/4666371.html