题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1099
There is a certain amount of night guards that are available to protect the local junkyard from possible junk robberies. These guards need to be scheduled in pairs so that each pair guards in a different night. The junkyard CEO ordered you to write a program which given the guards characteristics determines the maximum amount of scheduled guards (the rest will be fired). Please note that each guard can be scheduled with only one of his colleagues and no guard can work alone.
Input
The first line of the input contains one number N ≤ 222 which is a number of night guards. Unlimited number of lines consisting of unordered pairs ( i, j) follow, each such pair means that guard # i and guard # j can work together, because it is possible to find uniforms that suit both of them (The junkyard uses different parts of uniforms for different guards i.e. helmets, pants, jackets. It is impossible to put small helmet on a guard with a big head or big shoes on guard with small feet). The input ends with Eof.
Output
You should output one possible optimal assignment. On the first line of the output write the even number C, the amount of scheduled guards. Then output C/2 lines, each containing 2 integers ( i, j) that denote that i and j will work together.
Example
input | output |
---|---|
| |
题目翻译:
有一定数量的夜间警卫,可以保护当地的垃圾场免受可能的垃圾抢劫。这些卫兵需要成对安排,以便每对守卫在不同的夜晚。垃圾场首席执行官命令您编写一个程序,该程序给出防护特征,确定计划守卫的最大数量(其余人员将被解雇)。请注意,每个警卫只能安排与他的一名同事,没有警卫可以单独工作。
输入
输入的第一行包含一个数字N = 222,这是一些夜间防护装置。无限数量的线组成无序对 (i , j) 跟随, 每个这样的对意味着守卫 # i和守卫 # j可以一起工作, 因为有可能找到适合他们两人的制服 (垃圾场使用不同卫兵的不同部分制服,如头盔、裤子、夹克。不可能把小头盔放在一个长头或大鞋用小脚守卫的护罩上。输入以 Eof 结尾。
输出
应输出一个可能的最佳赋值。在输出的第一行上写偶数C,预定的防护装置的数量。然后输出C/2 行,每行包含 2 个整数 (i , j),表示i和j将协同工作。
经典的一般图匹配带花树算法,这个算法我也只是简单的会用板子,理解好难!,话不多说,上板子。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=300;
int N;
bool G[maxn][maxn];
int match[maxn];
bool InQueue[maxn],InPath[maxn],InBlossom[maxn];
int head,tail;
int Queue[maxn];
int start,finish;
int NewBase;
int father[maxn],Base[maxn];
int Count;
void CreateGraph(){
int u,v;
memset(G,0,sizeof(G));
scanf("%d",&N);
while(scanf("%d%d",&u,&v)!=EOF){
G[u][v]=G[v][u]=1;
}
}
void Push(int u){
Queue[tail++]=u;
InQueue[u]=1;
}
int Pop(){
int res=Queue[head++];
return res;
}
int FindCommonAncestor(int u,int v){
memset(InPath,0,sizeof(InPath));
while(true){
u=Base[u];
InPath[u]=1;
if(u==start)break;
u=father[match[u]];
}
while(true){
v=Base[v];
if(InPath[v])break;
v=father[match[v]];
}
return v;
}
void ResetTrace(int u){
int v;
while(Base[u]!=NewBase){
v=match[u];
InBlossom[Base[u]]=InBlossom[Base[v]]=1;
u=father[v];
if(Base[u]!=NewBase)father[u]=v;
}
}
void BlossomContract(int u,int v){
NewBase=FindCommonAncestor(u,v);
memset(InBlossom,0,sizeof(InBlossom));
ResetTrace(u);
ResetTrace(v);
if(Base[u]!=NewBase)father[u]=v;
if(Base[v]!=NewBase)father[v]=u;
for(int tu=1;tu<=N;tu++){
if(InBlossom[Base[tu]]){
Base[tu]=NewBase;
if(!InQueue[tu])Push(tu);
}
}
}
void FindAugmentingPath(){
memset(InQueue,0,sizeof(InQueue));
memset(father,0,sizeof(father));
for(int i=1;i<=N;i++){
Base[i]=i;
}
head=tail=1;
Push(start);
finish=0;
while(head<tail){
int u=Pop();
for(int v=1;v<=N;v++){
if(G[u][v]&&(Base[u]!=Base[v])&&match[u]!=v){
if((v==start)||(match[v]>0)&&father[match[v]]>0){
BlossomContract(u,v);
} else if(father[v]==0){
father[v]=u;
if(match[v]>0){
Push(match[v]);
} else {
finish=v;
return;
}
}
}
}
}
}
void AugmentPath(){
int u,v,w;
u=finish;
while(u>0){
v=father[u];
w=match[v];
match[v]=u;
match[u]=v;
u=w;
}
}
void Edmonds(){
memset(match,0,sizeof(match));
for(int u=1;u<=N;u++){
if(match[u]==0){
start=u;
FindAugmentingPath();
if(finish>0)AugmentPath();
}
}
}
void PrintMatch(){
Count=0;
for(int u=1;u<=N;u++){
if(match[u]>0)Count++;
}
printf("%d\n",Count);
for(int u=1;u<=N;u++){
if(u<match[u]){
printf("%d %d\n",u,match[u]);
}
}
}
int main(){
CreateGraph();
Edmonds();//进行匹配
PrintMatch();//输出匹配
return 0;
}