题目链接: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. luogu2261 [CQOI2007]余数求和

    除法分块. 猜想: 记 \(g(x)=\lfloor k / \lfloor k / x\rfloor \rfloor\),则对于 \(i \in [x,g(x)]\),\(\lfloor k / i ...

  2. Javascript拼接HTML字符串的方法列举及思路

    转载过来,去掉一些废话吧. 目标: 方便的拼接字符串,不使用让人眼晕的+=.使用过程如下: 1,先创建一个作为“模板”的字符串,如:’My name is ${name},I\’m ${age}.’ ...

  3. JavaEE JDBC 了解数据库连接池

    了解数据库连接池 @author ixenos 数据库连接是有限的资源,如果用户需要离开应用一段时间,那么他占用的连接就不应该保持开放状态: 另一方面,每次查询都获取连接并在随后关闭它的代价也很高. ...

  4. 【dfs+理解题意+构造】【待重做】codeforces E. Ice cream coloring

    http://codeforces.com/contest/805/problem/E [题意] 染色数是很好确定,最少染色数是max(si)(最小为1,即使所有的si都为0,这样是单节点树形成的森林 ...

  5. 【multimap的应用】D. Array Division

    http://codeforces.com/contest/808/problem/D #include<iostream> #include<cstdio> #include ...

  6. java中filter的用法

    filter过滤器主要使用于前台向后台传递数据是的过滤操作.程度很简单就不说明了,直接给几个已经写好的代码: 一.使浏览器不缓存页面的过滤器 Java代码   import javax.servlet ...

  7. 【Ural1297】Palindrome(后缀数组)

    题意:求一个字符串的最长回文子串 n<=1000 思路:这是一道论文题 需要注意的细节: 1.奇偶分类 2.中间的分割符与最后的附加字母都是最小值,但两者不能相同,否则height可能会出现问题 ...

  8. POJ3150:Cellular Automaton

    题意看不懂加题目想不通,很菜. n<=500个数围城环,每次操作对每个数Ai把与i在环上相距不超过d<n/2(包括Ai)的数加起来取模m<=1e6,求K<=1e7次操作后的环. ...

  9. msp430入门编程41

    msp430中C语言的软件工程--状态机建模

  10. iOS 用cornerstone 创建分支

    第一步:在cornerstone中添加服务器上的代码路径,如下: 第二步:选中服务器路径下的代码,选择“分支”按钮 第三步:开始创建分支 第四步:效果图如下 第五步:选择分支下的路径下载代码并进行修改 ...