http://blog.csdn.net/sdj222555/article/details/7426592
大意就是有n个人,每个人与其他的某几个人有关系,这个关系且称为浪漫关系,然后最后求一个最大的集合,使得集合中所有的人两两之间都不存在浪漫关系。
看到之后就可以发现,这是一道非常明显的最大独立集的问题,可以转化为二分图来做,还是最经典的拆点建图,然后根据定理,最大独立集=顶点数-最小点覆盖数。 而对于这道题来说,我们可以发现这个浪漫关系是相互的。
而我们的建图中,按理来说应该是一边是男的点,一边是女的点这样连边,但是题目中没说性别的问题。
只能将每个点拆成两个点,一个当作是男的点,一个当作是女的点了,然后连边。由于关系是相互的,这样就造成了边的重复。也就是边集是刚才的二倍,从而导致了最大匹配变成了二倍。
那么 ,最大独立集=顶点数-最大匹配/2,所以最终答案就呼之欲出了。
// File Name: 1466.cpp // Author: zlbing // Created Time: 2013/2/24 1:00:15 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define MAXN 505 int Left[MAXN]; int w[MAXN][MAXN]; bool S[MAXN],T[MAXN]; int N; bool match(int i) { S[i]=true; for(int j=1;j<=N;j++)if(w[i][j]&&!T[j]) { T[j]=true; if(Left[j]==0||match(Left[j])) { Left[j]=i; return true; } } return false; } int main(){ while(~scanf("%d",&N)) { int a,b,c; CL(w,0); CL(Left,0); for(int i=0;i<N;i++) { scanf("%d: (%d)",&a,&b); for(int j=0;j<b;j++) { scanf("%d",&c); w[a+1][c+1]=1; } } int sum=0; for(int i=1;i<=N;i++) { CL(S,0); CL(T,0); if(match(i))sum++; } printf("%d\n",N-(sum/2)); } return 0; }