UVA 1663 Purifying Machine (二分图匹配,最大流)
题意:
给m个长度为n的模板串,模板串由0和1和*三种组成,且每串至多1个*,代表可0可1。模板串至多匹配2个串,即*号改成0和1,如果没有*号则只能匹配自己。问:模板串可以缩减为几个,同样可以匹配原来m个串同样能匹配的所有串。
思路:
差点想不出是二分图匹配了。
将原来m个串所能匹配的串给取出来放到集合中(记得去重),编上号。并为他们黑白着色,源点到白色点有容量1的边,黑色点到汇点有容量为1的边,对于该白色点所能匹配的所有黑色点,都有一条容量为1的边。跑一次最大流,得知匹配对数,这些匹配的都只用1个模板串,不匹配的独用一个模板串。
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <deque>
#include <set>
#include <algorithm>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=;
int n, m, up;
char s[N][];
int col[N*], path[N*], flow[N*], edge_cnt;
vector<int> vect[N*];
vector<int> vec[N*]; struct node
{
int from, to, cap, flow;
node(){};
node(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){};
}edge[]; void add_node(int from,int to,int cap,int flow)
{
edge[edge_cnt]=node(from,to,cap,flow);
vect[from].push_back(edge_cnt++);
} bool ismatch(string &a,string &b) //只有一个位不同即为匹配
{
int cnt=;
for(int i=; i<n; i++)
if( a[i]!=b[i] ) cnt++;
if(cnt==) return true;
else return false;
} void color(int s,int c)
{
col[s]=c;
for(int i=; i<vec[s].size(); i++)
{
int t=vec[s][i];
if(!col[t]) color(t,-col[s]);
}
} set<string> sett;
string str[N*];
int build_graph()
{
//把包含*号的拆成两个数字,再转int,可能有重复。
sett.clear();
for(int i=; i<m; i++)
{
int j=;
for(; j<n; j++)
{
if(s[i][j]=='*')
{
s[i][j]='';
sett.insert( string(s[i]) ); //重复的自动去掉
s[i][j]='';
sett.insert( string(s[i]) );
break;
}
}
if(j==n) sett.insert( string(s[i]) );
} up=;
for(set<string>::iterator it=sett.begin(); it!=sett.end(); it++)
str[up++]=*it; for(int i=; i<=up+; i++) vect[i].clear(),vec[i].clear();//第二个vec是为了着色用的 for(int i=; i<up; i++) //匹配建无向图,着色用
{
for(int j=i+; j<up; j++)
if(ismatch(str[i],str[j]))
{
vec[i].push_back(j);
vec[j].push_back(i);
}
} //黑白着色
memset(col,,sizeof(col));
for(int i=; i<up; i++) if(!col[i]) color(i,); //添加源点and汇点,重新建图
memset(edge,,sizeof(edge));
edge_cnt=;
for(int i=; i<up; i++)
{
if(col[i]==) //0是源点
{
add_node(,i,,);
add_node(i,,,);
for(int j=; j<vec[i].size(); j++) //相邻的点颜色不同
{
int q=vec[i][j];
add_node(i,q,,);
add_node(q,i,,);
}
}
if(col[i]==) //up是汇点
{
add_node(i,up,,);
add_node(up,i,,);
}
}
} int BFS(int s,int e)
{
deque<int> que(,s);
flow[s]=INF;
while(!que.empty())
{
int x=que.front(); que.pop_front();
for(int i=; i<vect[x].size(); i++)
{
node e=edge[vect[x][i]];
if(e.cap>e.flow && !flow[e.to])
{
path[e.to]=vect[x][i];
flow[e.to]=min(flow[e.from], e.cap-e.flow);
que.push_back(e.to);
}
}
if(flow[e]) break;
}
return flow[e];
} int max_flow(int s,int e)
{
int ans_flow=;
while(true)
{
memset(flow,,sizeof(flow));
memset(path,,sizeof(path));
int tmp=BFS(s,e);
if(!tmp) return ans_flow;
ans_flow+=tmp; int ed=e;
while(ed!=s)
{
int t=path[ed];
edge[t].flow+=tmp;
edge[t^].flow-=tmp;
ed=edge[t].from;
}
}
} int main()
{
//freopen("input.txt", "r", stdin);
char c;
while(scanf("%d%d",&n,&m), n+m)
{
for(int i=; i<m; i++)//输入
{
for(int j=; j<n; )
{
c=getchar();
if(c=='*' || c=='' || c=='') s[i][j++]=c;
}
s[i][n]='\0';
}
build_graph();//建图
printf("%d\n",up--max_flow(,up));
}
return ;
}
AC代码
UVA 1663 Purifying Machine (二分图匹配,最大流)的更多相关文章
- UVa 1663 Purifying Machine (二分匹配)
题意:每一个01串中最多含有一个‘*’,‘*’既可表示0也可表示1,给出一些等长的这样的01串,问最少能用多少个这样的串表示出这些串. 如:000.010.0*1表示000.010.001.011,最 ...
- POJ 2724 Purifying Machine (二分图匹配)
题意 给定m个长度为n的01串(*既表示0 or 1.如*01表示001和101).现在要把这些串都删除掉,删除的方法是:①一次删除任意指定的一个:②如果有两个串仅有一个字符不同,则可以同时删除这两个 ...
- 最短路&生成树&二分图匹配&费用流问题
最短路 题意理解,建图 https://vjudge.net/problem/UVALive-4128 飞机票+行程建图 https://vjudge.net/problem/UVALive-3561 ...
- HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))
Marriage Match II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- cogs_14_搭配飞行员_(二分图匹配+最大流,网络流24题#01)
描述 http://cojs.tk/cogs/problem/problem.php?pid=14 有一些正飞行员和副飞行员,给出每个正飞行员可以和哪些副飞行员一起飞.一架飞机上必须一正一副,求最多多 ...
- BZOJ 3546 Life of the Party (二分图匹配-最大流)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3546 题意:给定一个二分图.(AB两个集合的点为n,m),边有K个.问去掉哪些点后 ...
- luogu P3386 【模板】二分图匹配
二次联通门 : luogu P3386 [模板]二分图匹配 /* luogu P3386 [模板]二分图匹配 最大流 设置源点,汇点,连到每条边上 跑一边最大流即可 */ #include <i ...
- UVa 二分图匹配 Examples
这些都是刘汝佳的算法训练指南上的例题,基本包括了常见的几种二分图匹配的算法. 二分图是这样一个图,顶点分成两个不相交的集合X , Y中,其中同一个集合中没有边,所有的边关联在两个集合中. 给定一个二分 ...
- 【最大流,二分图匹配】【hdu2063】【过山车】
题意:裸的求二分图匹配 建立一个源点 连向一边所有的点 容量为1; 另外一边点都连向汇点 容量为1; 二分图的边容量也为1 源点汇点求一遍最大流即可 #include <cstdio> ...
随机推荐
- 【BZOJ】【2440】【中山市选2011】完全平方数
莫比乌斯函数/容斥原理 PoPoQQQ讲义引入例题= = 比较水……就是莫比乌斯函数的简单应用,也可理解为乱容斥一下…… 二分答案——>求1~x有多少个无平方因子的数Q(x). 引用一下PoPo ...
- 【BZOJ】【2729】【HNOI2012】排队
排列组合+高精度 Orz PoPoQQQ 引用题解: 嗯……学习了一下python= =懒的写高精了 /************************************************ ...
- oracle一些函数
NVL( string1, replace_with):判断string1是否为空,如果是空就用replace_with代替. NVL2(E1, E2, E3)的功能为:如果E1为NULL,则函数返回 ...
- android 解析XML方式(三)
上一节中,我们使用SAX方式解析xml文档, SAX方式是基于事件驱动的.当然android的事件机制是基于回调函数的.在这一节中,我们用另外一种方式解析xml文档,这种方式也是基于事件驱动的,与SA ...
- mysql数据库主外键级联删除脚本RESTRICT --> CASCADE
在项目中,我们一般在数据库设计的时候做主外键关联设计,要么就不做.但是这样不符合规范,呵呵. 建立主外键关系的时候,默认是不能级联删除的.而出现往往在删除主表的数据时报错, 需要先删除从表然后再删除主 ...
- 利用Qemu Guest Agent (Qemu-ga) 实现 Openstack 监控平台
经常使用vmWare的同学都知道有vmware-tools这个工具,这个安装在vm内部的工具,可以实现宿主机与虚拟机的通讯,大大增强了虚拟机的性能与功能, 如vmware现在的Unity mode下可 ...
- 国产神通数据库操作备忘(Linux)
最近接触到国产神通数据库的一个项目,发现这个数据库还是挺有技术含量的,看起来做的还不错. 1.启动停止 在终端窗口中输入以下命令启动数据库: # /etc/init.d/oscardb_<数据库 ...
- 深入浅出Java并发包—锁机制(二)
接上文<深入浅出Java并发包—锁机制(一) > 2.Sync.FairSync.TryAcquire(公平锁) 我们直接来看代码 protected final boolean tr ...
- docker: "build" requires 1 argument. See 'docker build --help'.
http://bbs.csdn.net/topics/391040030 docker build --tag="ouruser/sinatra:v3" -<Dockerf ...
- mysql级联删除更新
首先,目前在产品环境可用的MySQL版本(指4.0.x和4.1.x)中,只有InnoDB引擎才允许使用外键,所以,我们的数据表必须使用InnoDB引擎. 下面,我们先创建以下测试用数据库表: CREA ...