题意:

有n个插座,m个设备以及k种转化器(每种转化器视为有无限个)。

转换器A->B可以将A类型的插头转化成B类型的插头,所以可以插在B类型的插座上。

求最少剩多少不匹配的设备。

分析:

抛开转换器不讲,插头插在插座上就是一个最大二分图匹配。

可以用最大流的算法,增加一个连接每个插头的源点s和连接每个插座的汇点t,每条弧容量都为1.

然后求最大流量,就是二分图的最大基数匹配。

既然有了转换器,一种插头可以用转换器转换成多种类型的插头,所以可以Floyd一次,求出每种插头可以转换成的所有的插头类型。

然后构二分图,求最大匹配即可。

 #include <bits/stdc++.h>

 using namespace std;

 const int maxn =  + ;

 vector<string> names;
int ID(const string& s)
{
for(int i = ; i < names.size(); ++i)
if(names[i] == s) return i;
names.push_back(s);
return names.size() - ;
} int n, m, k;
bool d[maxn][maxn];
int target[maxn], device[maxn]; const int INF = ; struct Edge
{
int from, to, cap, flow;
Edge(int u=, int v=, int c=, int f=):from(u), to(v), cap(c), flow(f) {}
}; struct EdmondsKarp
{
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
int a[maxn];
int p[maxn]; void Init(int n)
{
for(int i = ; i < n; ++i) G[i].clear();
edges.clear();
} void AddEdge(int from, int to, int cap)
{
edges.push_back(Edge(from, to, cap, ));
edges.push_back(Edge(to, from, , ));
m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} int MaxFlow(int s, int t)
{
int flow = ;
for(;;)
{
memset(a, , sizeof(a));
queue<int> Q;
Q.push(s);
a[s] = INF;
while(!Q.empty())
{
int x = Q.front(); Q.pop();
for(int i = ; i < G[x].size(); ++i)
{
Edge& e = edges[G[x][i]];
if(!a[e.to] && e.cap > e.flow)
{
p[e.to] = G[x][i];
a[e.to] = min(a[x], e.cap - e.flow);
Q.push(e.to);
}
}
if(a[t]) break;
}
if(!a[t]) break;
for(int u = t; u != s; u = edges[p[u]].from)
{
edges[p[u]].flow += a[u];
edges[p[u]^].flow -= a[u];
}
flow += a[t];
}
return flow;
}
}; EdmondsKarp g; int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--)
{
names.clear();
memset(d, , sizeof(d));
string s1, s2;
scanf("%d", &n);
for(int i = ; i < n; ++i) { cin >> s1; target[i] = ID(s1); }
scanf("%d", &m);
for(int i = ; i < m; ++i) { cin >> s1 >> s2; device[i] = ID(s2); }
scanf("%d", &k);
for(int i = ; i < k; ++i) { cin >> s1 >> s2; d[ID(s1)][ID(s2)] = true; }
//Floyd
int V = names.size();
for(int k = ; k < V; ++k)
for(int i = ; i < V; ++i)
for(int j = ; j < V; ++j)
d[i][j] |= d[i][k] && d[k][j]; //Build Graph
g.Init(V+);
for(int i = ; i < m; ++i) g.AddEdge(V, device[i], );//源点到每个设备
for(int i = ; i < n; ++i) g.AddEdge(target[i], V+, );//每个插座到汇点
for(int i = ; i < m; ++i)
for(int j = ; j < n; ++j)
if(d[device[i]][target[j]]) g.AddEdge(device[i], target[j], INF);
int ans = g.MaxFlow(V, V+);
printf("%d\n", m-ans);
if(T) puts("");
} return ;
}

代码君

紫书后面又介绍了一种更简单的做法,就是直接把k种转换器对应的k条弧加到图中去,然后求最大流。

代码就不贴了,=_=||

UVa 753 (二分图最大匹配) A Plug for UNIX的更多相关文章

  1. UVA 753 A Plug for UNIX(二分图匹配)

    A Plug for UNIX You are in charge of setting up the press room for the inaugural meeting of the Unit ...

  2. POJ 1087 A Plug for UNIX / HDU 1526 A Plug for UNIX / ZOJ 1157 A Plug for UNIX / UVA 753 A Plug for UNIX / UVAlive 5418 A Plug for UNIX / SCU 1671 A Plug for UNIX (网络流)

    POJ 1087 A Plug for UNIX / HDU 1526 A Plug for UNIX / ZOJ 1157 A Plug for UNIX / UVA 753 A Plug for ...

  3. UVA 753 - A Plug for UNIX(网络流)

      A Plug for UNIX  You are in charge of setting up the press room for the inaugural meeting of the U ...

  4. 【poj1087/uva753】A Plug for UNIX(最大流)

    A Plug for UNIX   Description You are in charge of setting up the press room for the inaugural meeti ...

  5. POJ 2226二分图最大匹配

    匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...

  6. POJ2239 Selecting Courses(二分图最大匹配)

    题目链接 N节课,每节课在一个星期中的某一节,求最多能选几节课 好吧,想了半天没想出来,最后看了题解是二分图最大匹配,好弱 建图: 每节课 与 时间有一条边 #include <iostream ...

  7. poj 2239 二分图最大匹配,基础题

    1.poj 2239   Selecting Courses   二分图最大匹配问题 2.总结:看到一个题解,直接用三维数组做的,很巧妙,很暴力.. 题意:N种课,给出时间,每种课在星期几的第几节课上 ...

  8. UESTC 919 SOUND OF DESTINY --二分图最大匹配+匈牙利算法

    二分图最大匹配的匈牙利算法模板题. 由题目易知,需求二分图的最大匹配数,采取匈牙利算法,并采用邻接表来存储边,用邻接矩阵会超时,因为邻接表复杂度O(nm),而邻接矩阵最坏情况下复杂度可达O(n^3). ...

  9. 二分图最大匹配的K&#246;nig定理及其证明

     二分图最大匹配的K?nig定理及其证明 本文将是这一系列里最短的一篇,因为我只打算把K?nig定理证了,其它的废话一概没有.    以下五个问题我可能会在以后的文章里说,如果你现在很想知道的话,网上 ...

随机推荐

  1. php入门变量之字符串

    字符串只是一块用引号括起来的字符:字母.数字.空格.标点符号,等等. 下面列出的全都是字符串: 'Huige' "In watermelon sugar" '100' 'Augus ...

  2. Oracle 动态视图1 V$LOCK

    v$lock显示数据库当前持有锁情况 Column Datatype Description SID NUMBER 会话ID TYPE VARCHAR2(2) 表示锁的类型.值包括TM,TX,等 ID ...

  3. what is the virtual machine, when and why we need use it ?

    虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统. 通过虚拟机软件,你可以在一台物理计算机上模拟出二台或多台虚拟的计算机,这些虚 ...

  4. jsp与servlet之间的参数传递【转】

    JSP与 servlet之间的传值有两种情况:JSP -> servlet, servlet -> JSP. 通过对象 request和 session (不考虑 application) ...

  5. MySQL --slave-skip-errors

    官方说明: --slave-skip-errors=[err_code1,err_code2,...|all] (MySQL Cluster NDB 7.0.33 and later; MySQL C ...

  6. UUID为36位

    package util; import java.util.UUID; public class UUIDUtil { public static UUID getId(){ return UUID ...

  7. python 练习题

    python是一个功能很强大的语言,他可以解决各种在数学问题,下面我分享一些练习题供大家参考: 有关正态分布的问题: # -*- coding: cp936 -*- import math a=0 u ...

  8. 关于WinForm引用WPF窗体

    项目中有个界面展示用WPF实现起来比较简单,并且能提供更酷炫的效果,但是在WinForm中使用WPF窗体出现了问题,在网上找了一下有些人说Winform不能引用WPF的窗体,我就很纳闷,Win32都能 ...

  9. CROSS APPLY vs OUTER APPLY

    Apply 工作原理:    Apply操作符让符合查询的每一条记录都调用一次TVF函数,并将结果与原数据表的记录内容一起展开.    Apply操作符定义在From子句内,使用方式与Join操作符类 ...

  10. c++ 字符串工具类

    #include <string> #include "util.h" namespace strtool{ std::string trim(const std::s ...