题目链接:https://vjudge.net/problem/URAL-1099

1099. Work Scheduling

Time limit: 0.5 second
Memory limit: 64 MB
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 (ij) 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 (ij) that denote that i and j will work together.

Sample

input output
3
1 2
2 3
1 3
2
1 2

题解:

一般图匹配带花树的模板题。还是看不太懂,以后有时间再看看。

有关怎么找到奇环:

其中可以把最右边两个点看成是找到奇环时的两个点,其中root为他们的LCA。

疑问1:什么要把花上的边的方向取反?

疑问2:为什么在找奇环时要特判 v==start ?

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
const int INF = 2e9;
const int MOD = 1e9+;
const int MAXM = +;
const int MAXN = 2e3+; int N;
bool graph[MAXN][MAXN];
int match[MAXN];
bool inque[MAXN], inpath[MAXN], inblos[MAXN];
queue<int>q;
int start, finish;
int newbase, fa[MAXN], base[MAXN]; int FindCommonAncester(int u, int v) //仅仅是找LCA,并不修改任何值
{
memset(inpath, false, sizeof(inpath));
while(true)
{
u = base[u];
inpath[u] = true;
if(u==start) break;
u = fa[match[u]];
}
while(true)
{
v = base[v];
if(inpath[v]) break;
v = fa[match[v]];
}
return v;
} void ResetTrace(int u) //把fa的方向取反
{
int v;
while(base[u]!=newbase) //匹配边、非匹配边交替出现
{
v = match[u]; //u--match[u]匹配边
inblos[base[u]] = inblos[base[v]] = true;
u = fa[v]; //v--fa[v]非匹配边
if(base[u]!=newbase) fa[u] = v;
}
} void BloosomContract(int u, int v)
{
newbase = FindCommonAncester(u, v);
memset(inblos, false, sizeof(inblos));
ResetTrace(u); //把u到LCA上的边取反
ResetTrace(v); //把v到LCA上的边取反
if(base[u]!=newbase) fa[u] = v; //看不懂
if(base[v]!=newbase) fa[v] = u; for(int tu = ; tu<=N; tu++)
if(inblos[base[tu]])
{
base[tu] = newbase; //设置它属于的集合
if(!inque[tu]) q.push(tu); //在花中的点加入队列,因为与花中点相连的点还可以找增广路
}
} void FindAugmentingPath()
{
memset(inque, false, sizeof(inque));
memset(fa, , sizeof(fa));
for(int i = ; i<=N; i++)
base[i] = i;
while(!q.empty()) q.pop();
q.push(start);
finish = ; while(!q.empty())
{
int u = q.front(); q.pop(); for(int v = ; v<=N; v++) //fa[u]--u是匹配边, u--v是未匹配边。
if(graph[u][v] && base[u]!=base[v] && match[u]!=v )
{
//为什么要特判 v==start ?
if( (v==start) || (match[v]> && fa[match[v]]>)) //找到奇环。
BloosomContract(u, v);
else if(fa[v]==) //v点在这次找增广路时没有被访问
{
fa[v] = u;
if(match[v]>) //如果已经匹配了,则加入他的匹配点,继续找增广路。
q.push(match[v]);
else //如果没有匹配,则找到了增广路。
{
finish = v;
return;
}
}
}
}
} void AugmentPath()
{
int u, v, w;
u = finish;
while(u>) //沿着增广路往回走,把匹配边和非匹配边取反
{
v = fa[u];
w = match[v];
match[v] = u;
match[u] = v;
u = w;
}
} void Edmonds()
{
memset(match, , sizeof(match));
for(int u = ; u<=N; u++)
if(match[u]==)
{
start = u;
FindAugmentingPath();
if(finish>) AugmentPath();
}
} int main()
{
scanf("%d", &N);
memset(graph, false, sizeof(graph));
int u, v;
while(scanf("%d%d", &u, &v)!=EOF)
graph[u][v] = graph[v][u] = true; Edmonds();
int sum = ;
for(int u = ; u<=N; u++)
if(match[u]>) sum++;
printf("%d\n", sum);
for(int u = ; u<=N; u++)
if(u<match[u])
printf("%d %d\n", u, match[u]); return ;
}

URAL1099 Work Scheduling —— 一般图匹配带花树的更多相关文章

  1. URAL 1099. Work Scheduling (一般图匹配带花树)

    1099. Work Scheduling Time limit: 0.5 secondMemory limit: 64 MB There is certain amount of night gua ...

  2. kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树

    二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j ...

  3. HDU 4687 Boke and Tsukkomi (一般图匹配带花树)

    Boke and Tsukkomi Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Othe ...

  4. URAL1099. Work Scheduling(一般图匹配带花树开花算法)

    1099. Work Scheduling Time limit: 0.5 second Memory limit: 64 MB There is certain amount of night gu ...

  5. HDU 4687 Boke and Tsukkomi 一般图匹配,带花树,思路,输出注意空行 难度:4

    http://acm.hdu.edu.cn/showproblem.php?pid=4687 此题求哪些边在任何一般图极大匹配中都无用,对于任意一条边i,设i的两个端点分别为si,ti, 则任意一个极 ...

  6. HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力

    一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...

  7. ZOJ 3316 Game 一般图最大匹配带花树

    一般图最大匹配带花树: 建图后,计算最大匹配数. 假设有一个联通块不是完美匹配,先手就能够走那个没被匹配到的点.后手不论怎么走,都必定走到一个被匹配的点上.先手就能够顺着这个交错路走下去,最后一定是后 ...

  8. 【learning】一般图最大匹配——带花树

    问题描述 ​ 对于一个图\(G(V,E)\),当点对集\(S\)满足任意\((u,v)\in S\),均有\(u,v\in V,(u,v)\in E\),且\(S\)中没有点重复出现,我们称\(S\) ...

  9. UOJ #79 一般图最大匹配 带花树

    http://uoj.ac/problem/79 一般图和二分图的区别就是有奇环,带花树是在匈牙利算法的基础上对奇环进行缩点操作,复杂度似乎是O(mn)和匈牙利一样. 具体操作是一个一个点做类似匈牙利 ...

随机推荐

  1. 大数据学习——mapreduce倒排索引

    数据 a.txt hello jerry hello tom b.txt allen tom allen jerry allen hello c.txt hello jerry hello tom 1 ...

  2. ExtJs 滚动条问题

    bodyStyle :'overflow-x:visible;overflow-y:scroll', //隐藏水平滚动条 通过这个方法可以显示或隐藏滚动条 var form = new Ext.for ...

  3. 什么是Kubernetes?

    刚刚进学校实验室,第一次开会导师和小组同学说了n次Kubernetes,从来没听过,一脸懵逼. Kubernetes也有很多人把它叫K8S, 原文链接:http://omerio.com/2015/1 ...

  4. 【概率dp】D. Card Collector

    https://www.bnuoj.com/v3/contest_show.php?cid=9147#problem/D [题意] 为了集齐n张卡片,必须要买多少袋零食?题目给定每种卡片出现在零食中的 ...

  5. Rem 字体设置学习一

    JS方法动态计算根元素的字体大小: [淘宝首页:m.taobao.com] (function (doc, win) { var docEl = doc.documentElement, resize ...

  6. POJ 2109 Power of Cryptography【高精度+二分 Or double水过~~】

    题目链接: http://poj.org/problem?id=2109 参考: http://blog.csdn.net/code_pang/article/details/8263971 题意: ...

  7. Codeforces Round #291 (Div. 2) B. Han Solo and Lazer Gun

    因为是x,y均为整数因此对于同一直线的点,其最简分数x/y是相同的(y可以为0,这里不做除法)于是将这些点不断求最简分数用pair在set中去重即可. #include <cmath> # ...

  8. java代码编译过程

    简单随笔 java程序需要先编译成class文件然后才能执行,由于是编程成立机器代码,虚拟机加载内存的时候更快的执行. java文件编译成class文件步骤如下: 1)词法分析,检查每一个关键字单词是 ...

  9. Spring基于Java的JSR-250注解

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/annotation-based-configuration/spring-jsr250-annot ...

  10. [转] ubuntu 下mongodb的安装-----这篇文章也不错

    在Ubuntu下进行MongoDB安装步骤 一. 在Ubuntu下最傻瓜的步骤(以下都在root用户下进行操作): 1.运行"apt-get install mongo" 如果遇到 ...