zoukankan      html  css  js  c++  java
  • POJ 1466 Girls and Boys 黑白染色 + 二分匹配 (最大独立集) 好题

    有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 }
    View Code
  • 相关阅读:
    java8
    Python isinstance()
    Python3 File next()
    np.array() 与 np.mat() 比较
    np.nonzero()
    np.dot()
    算法之归并排序的应用 —— 小和问题以及逆序对问题
    递归过程以及递归master公式
    算法之异或运算及其应用
    算法之二分法及其应用
  • 原文地址:https://www.cnblogs.com/-maybe/p/4716688.html
Copyright © 2011-2022 走看看