有n个人, 其中有男生和女生,接着有n行,分别给出了每一个人暗恋的对象(不止暗恋一个)
现在要从这n个人中找出一个最大集合,满足这个集合中的任意2个人,都没有暗恋这种关系。
输出集合的元素个数。
刚开始想,把人看成顶点,若有暗恋的关系,就连一条边,构成一个图
独立集的概念:一个图中两两互不相连的顶点集合
所以这道题,就是要求最大独立集
有:最大独立集+最小顶点覆盖=|V|(顶点的总个数)
那就求最小顶点覆盖了
根据题意:
暗恋的对象性别不同,所以a暗恋b,b暗恋c,c暗恋a这种关系不可能存在
也就是说,这个图的顶点可以根据性别分成2个集合,男生和女生
即这是一个二分图
我们知道,在二分图中,最小顶点覆盖=最大匹配
则:最大独立集=|V|-最大匹配
所以思路就清晰了:
1.黑白染色:确定男生和女生
2.建图:s连边到所有男生,所有女生连边到t,若男生i和女生j有关系,则连一条边,边的容量都是1
3.二分匹配转化为最大流求解
4.|V|-最大匹配
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 6 using namespace std; 7 8 const int maxn=505; 9 const int inf=0x3f3f3f3f; 10 int s; 11 int t; 12 13 inline int min(int x,int y) 14 { 15 return x<y?x:y; 16 } 17 18 struct Edge 19 { 20 int to,cap,rev; 21 }; 22 vector<Edge>edge[maxn]; 23 int level[maxn]; 24 int iter[maxn]; 25 int dye[maxn]; 26 27 void addedge(int from,int to,int cap) 28 { 29 edge[from].push_back((Edge){to,cap,edge[to].size()}); 30 edge[to].push_back((Edge){from,0,edge[from].size()-1}); 31 } 32 33 struct Edge1 34 { 35 int to,next; 36 }; 37 Edge1 edge1[maxn*100]; 38 int head[maxn],tot; 39 40 void init() 41 { 42 memset(head,-1,sizeof head); 43 tot=0; 44 memset(dye,-1,sizeof dye); 45 } 46 47 void addedge1(int from,int to) 48 { 49 edge1[tot].to=to; 50 edge1[tot].next=head[from]; 51 head[from]=tot++; 52 } 53 54 void get_dye(int u,int pre) 55 { 56 if(pre==-1) 57 dye[u]=1; 58 else 59 dye[u]=!dye[pre]; 60 for(int i=head[u];~i;i=edge1[i].next) 61 { 62 int v=edge1[i].to; 63 if(v==pre) 64 continue; 65 if(dye[v]!=-1) 66 continue; 67 get_dye(v,u); 68 } 69 } 70 71 void build_graph(int n) 72 { 73 s=n; 74 t=n+1; 75 for(int i=0;i<=t;i++) 76 edge[i].clear(); 77 for(int i=0;i<n;i++) 78 { 79 if(dye[i]==1) 80 { 81 addedge(s,i,1); 82 for(int j=head[i];~j;j=edge1[j].next) 83 { 84 int v=edge1[j].to; 85 addedge(i,v,1); 86 } 87 } 88 else 89 addedge(i,t,1); 90 } 91 } 92 93 void bfs() 94 { 95 memset(level,-1,sizeof level); 96 queue<int>que; 97 while(!que.empty()) 98 que.pop(); 99 que.push(s); 100 level[s]=1; 101 while(!que.empty()) 102 { 103 int u=que.front(); 104 que.pop(); 105 for(int i=0;i<edge[u].size();i++) 106 { 107 Edge &e=edge[u][i]; 108 if(e.cap>0&&level[e.to]<0) 109 { 110 level[e.to]=level[u]+1; 111 que.push(e.to); 112 } 113 } 114 } 115 } 116 117 int dfs(int u,int f) 118 { 119 if(u==t) 120 return f; 121 for(int &i=iter[u];i<edge[u].size();i++) 122 { 123 Edge &e=edge[u][i]; 124 if(e.cap>0&&level[e.to]>level[u]) 125 { 126 int d=dfs(e.to,min(e.cap,f)); 127 if(d) 128 { 129 e.cap-=d; 130 edge[e.to][e.rev].cap+=d; 131 return d; 132 } 133 } 134 } 135 return 0; 136 } 137 138 int solve() 139 { 140 int flow=0; 141 while(1) 142 { 143 bfs(); 144 if(level[t]<0) 145 return flow; 146 memset(iter,0,sizeof iter); 147 int f; 148 while(f=dfs(s,inf)) 149 { 150 flow+=f; 151 } 152 } 153 } 154 155 int main() 156 { 157 int n; 158 while(~scanf("%d",&n)) 159 { 160 init(); 161 for(int i=0;i<n;i++) 162 { 163 int j; 164 char ch; 165 scanf("%d%c",&j,&ch); 166 char str[10]; 167 scanf("%s",str); 168 int len=strlen(str); 169 int num=0; 170 for(int k=1;k<len-1;k++) 171 { 172 num=num*10+(str[k]-'0'); 173 } 174 for(int k=0;k<num;k++) 175 { 176 int tmp; 177 scanf("%d",&tmp); 178 addedge1(j,tmp); 179 addedge1(tmp,j); 180 } 181 } 182 183 for(int i=0;i<n;i++) 184 { 185 if(dye[i]==-1) 186 get_dye(i,-1); 187 } 188 build_graph(n); 189 printf("%d ",n-solve()); 190 } 191 return 0; 192 }