POJ 2444 The Accomodation of Students 黑白染色+二分匹配 簡單題

有n個人,編號為1~n,其中有m對朋友,現在給出m對朋友,問能不能把這n個人分成2個組,使得每一個組裡面的人都是互相不認識的?

若不可以,輸出No

若可以,問現在將認識的人兩兩配對,輸出最多可以有多少對

說白了,這道題就是首先要判斷是不是二分圖,不是的話輸出No,是的話輸出最大匹配

判斷二分圖:用黑白染色法,注意,整個關係圖有可能是不連通的,所以要遍歷所有的點

這裡求最大匹配不是用匈牙利算法,而是直接轉化為最大流

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 using namespace std;
  5 
  6 const int maxn=210;
  7 const int inf=0x3f3f3f3f;
  8 
  9 inline int min(int a,int b)
 10 {
 11     return a<b?a:b;
 12 }
 13 
 14 bool link[maxn][maxn];
 15 struct Edge
 16 {
 17     int to,next;
 18 };
 19 Edge edge[maxn*maxn*2];
 20 int head[maxn];
 21 int tot;
 22 bool flag;
 23 int dye[maxn];
 24 int level[maxn];
 25 int iter[maxn];
 26 const int s=0;
 27 int t;
 28 
 29 void addedge(int u,int v)
 30 {
 31     edge[tot].to=v;
 32     edge[tot].next=head[u];
 33     head[u]=tot++;
 34 }
 35 
 36 void init(int n)
 37 {
 38     memset(link,false,sizeof link);
 39     memset(head,-1,sizeof head);
 40     memset(dye,-1,sizeof dye);
 41     tot=0;
 42     flag=true;
 43 }
 44 
 45 void to_dye(int pre ,int u)
 46 {
 47     if(pre==-1)
 48         dye[u]=1;
 49     else
 50         dye[u]=!dye[pre];
 51 
 52     for(int i=head[u];~i;i=edge[i].next)
 53     {
 54         int v=edge[i].to;
 55         if(v==pre)
 56             continue;
 57         if(dye[v]!=-1)
 58         {
 59             if(dye[v]!=dye[u])
 60                 continue;
 61             else
 62             {
 63                 flag=false;
 64             }
 65         }
 66         else
 67          to_dye(u,v);
 68     }
 69 }
 70 
 71 struct Flow_Edge
 72 {
 73     int to,cap,rev;
 74 };
 75 vector<Flow_Edge>flow_edge[maxn];
 76 
 77 void add(int from,int to,int cost)
 78 {
 79     flow_edge[from].push_back((Flow_Edge){to,cost,flow_edge[to].size()});
 80     flow_edge[to].push_back((Flow_Edge){from,0,flow_edge[from].size()-1});
 81 }
 82 
 83 void build_graph(int n)
 84 {
 85     for(int i=0;i<=n;i++)
 86         flow_edge[i].clear();
 87 
 88     t=n+1;
 89     for(int i=1;i<=n;i++)
 90     {
 91         if(dye[i]==1)
 92             add(s,i,1);
 93         else
 94             add(i,t,1);
 95     }
 96     for(int i=1;i<=n;i++)
 97     {
 98         for(int j=1;j<=n;j++)
 99         {
100             if(i==j)
101                 continue;
102             if(link[i][j]||link[j][i])
103             {
104                 if(dye[i]==1)
105                     add(i,j,1);
106                 else
107                     add(j,i,1);
108                 link[i][j]=false;
109                 link[j][i]=false;
110             }
111         }
112     }
113 }
114 
115 void bfs()
116 {
117     memset(level,-1,sizeof level);
118     queue<int>que;
119     while(!que.empty())
120         que.pop();
121     level[s]=1;
122     que.push(s);
123     while(!que.empty())
124     {
125         int u=que.front();
126         que.pop();
127         for(int i=0;i<flow_edge[u].size();i++)
128         {
129             Flow_Edge &e=flow_edge[u][i];
130             if(e.cap>0&&level[e.to]<0)
131             {
132                 level[e.to]=level[u]+1;
133                 que.push(e.to);
134             }
135         }
136     }
137 }
138 
139 int dfs(int u,int f)
140 {
141     if(u==t)
142         return f;
143     for(int &i=iter[u];i<flow_edge[u].size();i++)
144     {
145         Flow_Edge &e=flow_edge[u][i];
146         if(e.cap>0&&level[e.to]>level[u])
147         {
148             int d=dfs(e.to,min(e.cap,f));
149             if(d>0)
150             {
151                 e.cap-=d;
152                 flow_edge[e.to][e.rev].cap+=d;
153                 return d;
154             }
155         }
156     }
157     return 0;
158 }
159 
160 int max_flow(int n)
161 {
162     int flow=0;
163     while(1)
164     {
165         bfs();
166         if(level[t]==-1)
167             return flow;
168         memset(iter,0,sizeof iter);
169         int f;
170         while(f=dfs(s,inf))
171         {
172             if(f>0)
173                 flow+=f;
174         }
175     }
176 }
177 
178 int main()
179 {
180     int n,m;
181     while(~scanf("%d%d",&n,&m))
182     {
183         init(n);
184 
185         for(int i=0;i<m;i++)
186         {
187             int u,v;
188             scanf("%d%d",&u,&v);
189             link[u][v]=link[v][u]=true;
190             addedge(u,v);
191             addedge(v,u);
192         }
193 
194         for(int i=1;i<=n;i++)
195         {
196             if(dye[i]==-1)
197                 to_dye(-1,i);
198         }
199 
200         //printf("eee
");
201 
202         if(!flag)
203         {
204             printf("No
");
205             continue;
206         }
207         else
208         {
209             build_graph(n);
210             int flow=max_flow(n);
211             printf("%d
",flow);
212         }
213     }
214     return 0;
215 }
View Code
原文地址:https://www.cnblogs.com/-maybe/p/4693057.html