码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1466 Girls and Boys 黑白染色 + 二分匹配 (最大独立集) 好题

时间:2015-08-10 00:11:21      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

有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",n-solve());
190     }
191     return 0;
192 }
View Code

 

POJ 1466 Girls and Boys 黑白染色 + 二分匹配 (最大独立集) 好题

标签:

原文地址:http://www.cnblogs.com/-maybe/p/4716688.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!