POJ1043 What's In A Name?
题目来源:http://poj.org/problem?id=1043
题目大意:
一个犯罪团伙有n个成员,每人有一个唯一的字符串作为id,每人还有一个唯一的字符串作为name。该团伙有一个hideout系统,成员利用这个系统进行通信。成员进入hideout后可以发出信息,发出的信息会留下发送者的id。现在FBI获得了hideout的log记录,包括成员进入和离开的记录以及系统中发送信息的记录。其中,成员进入和离开记录的是他们的name,发送的信息记录的是id。成员只有在hideout中才能发送信息。整个log中每个成员至少出现一次,但不一定每个人都会发送信息。FBI希望通过这些记录确定犯罪团伙中每个成员的name和id的匹配关系。hideout初始时视为没有人。
输入:由单个测试用例组成。第一行整数n表示人数。第二行n个字符串表示每个人的id。接下来的每行为一条记录。由一个字符和一个字符串组成。‘E’表示进入,‘L’表示离开,后面的字符串是该人的name,‘M’表示发送了一条信息,后面接发送人id。‘Q’表示结束。
输出:输出由n行组成,每行输出name:id的匹配对,若某个name无法确定其id输出name:???。按name字典序输出。
Sample Input
7
bigman mangler sinbad fatman bigcheese frenchie capodicapo
E mugsy
E knuckles
M bigman
M mangler
L mugsy
E clyde
E bonnie
M bigman
M fatman
M frenchie
L clyde
M fatman
E ugati
M sinbad
E moriarty
E booth
Q
Sample Output
bonnie:fatman
booth:???
clyde:frenchie
knuckles:bigman
moriarty:???
mugsy:mangler
ugati:sinbad
该题与二部图的匹配问题紧密相关。之前的一篇博客已经介绍过了这道题里要用到的与二部图相关的理论基础。
请戳:http://www.cnblogs.com/dengeven/p/3230406.html
但是仅仅意识到与二部图匹配有关还不足以解决问题,因为我们要找的是确定会出现在完全匹配中的边。
首先,图的建立就是有小技巧的。如果按log顺序处理,每发出一条信息,连接在hideout中的name与信息显示的id,当有人离开发现矛盾再删除边这样的策略的话,可能被漏掉的情况很多,因为有人可能没有发出信息,即有的id不会显示在log中。简便的处理方法是初始时把所有连接都设为true,当出现一条信息时,删掉该id与不在hideout中的name的连接。这样就不会漏掉边。
然后,因为id与name是一一对应的,其实也就是说图应该有唯一的完全匹配,匹配数为n。确定每个name对于的id的方法是:遍历与name相接的每条边,如果去掉该条边,剩余图的最大匹配数小于n,说明这条边一定是唯一完全匹配中的,即与该name匹配的id可以确定,否则无法确定。
//////////////////////////////////////////////////////////////////////////
// POJ1043 What's In A Name
// Memory: 252K Time: 16MS
// Language: C++ Result: Accepted
////////////////////////////////////////////////////////////////////////// #include <cstring>
#include <iostream>
#include <algorithm> using namespace std; int n; //人数
char id[][]; //记录每个id
char name[][]; //记录每个name
int order[]; //name字典序序号
bool in_hideout[];//in_hideout[i]为true表示第i个人在hideout内
bool graph[][]; //graph[i][j]为true表示第i个name与第j个id有可能匹配
int link_name[]; //link_name[i]:匹配中与id为i的顶点相连的name编号
bool visited[]; //顶点访问标记数组
int match_id[]; //match_id[i]为确定后第i个name匹配的id号,不确定的为-1 inline int cmp(int i,int j){
if (memcmp(name[i],name[j],sizeof name[i]) <= ) return ;
else return ;
} //dfs寻找增广路
int findPath(int k){
for (int i = ; i < n; ++i) {
if (graph[k][i] && visited[i] == false){
visited[i] = true;
if (link_name[i] == - || findPath(link_name[i])){
link_name[i] = k;
return ;
}
}
}
return ;
} //匈牙利算法求最大匹配
int hungary(){
int cnt = ;
memset(link_name,-,sizeof(link_name));
for (int i = ; i < n; ++i) {
memset(visited, , sizeof(visited));
cnt += findPath(i);
}
return cnt; //最大匹配数
} int main(){
cin >> n;
for (int i = ; i < n; ++i) cin >> id[i];
memset(graph, true, sizeof(graph));
memset(match_id, -, sizeof(match_id));
memset(in_hideout, false, sizeof(in_hideout));
int name_cnt = ;
char log_type;
char buf[];
while (true) {
cin >> log_type;
if (log_type == 'Q') break;
cin >> buf;
int i;
switch (log_type){
case 'E':
for (i = ; i < name_cnt && strcmp(buf, name[i]) != ; ++i);
if (i == name_cnt) {
strcpy(name[name_cnt++], buf);
}
in_hideout[i] = ;
break;
case 'L':
for (i = ; i < name_cnt && strcmp(buf, name[i]) != ; ++i);
in_hideout[i] = ;
break;
case 'M':
for (i = ; i < n && strcmp(buf,id[i]) != ; ++i);
for (int j = ; j < n; ++j) {
if (!in_hideout[j]) {
graph[j][i] = false;
}
}
break;
}
}
for (int i = ; i < n; ++i){
for (int j = ;j < n; ++j) {
if (graph[i][j]) {
graph[i][j] = false;
if (hungary() != n) {
//该边是最大匹配的必须边,是确定的匹配
graph[i][j] = true;
match_id[i] = j;
break;
}
graph[i][j] = true;
}
}
}
for (int i = ; i < n; ++i) order[i] = i; //按name字典序输出
sort(order,order + n,cmp);
for (int i = ;i < n;i ++){
cout << name[order[i]] << ":";
if (match_id[order[i]] == -) {
cout << "???" << endl;
} else {
cout << id[match_id[order[i]]] << endl;
}
}
system("pause");
return ;
}
POJ1043 What's In A Name?的更多相关文章
- POJ1043问题描述
Description The FBI is conducting a surveillance of a known criminal hideout which serves as a commu ...
随机推荐
- 【leetcode刷题笔记】Search a 2D Matrix
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...
- xml字符串转xml对象,xml对象转json对象
xml字符串转xml对象: function loadXml(str) { if (str == null) { return null; } var doc = str; try{ doc = cr ...
- WEBRTC基本介绍
“WebRTC,名称源自网页实时通信(Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的技术,是谷歌2010年以6820万美元收购Glob ...
- APIO2017 游记
参加了APIO的同学肯定知道我为什么只写标题不写内容. QAQ
- 检测 iOS 的 APP 性能的一些方法
本文转载于微信公众号:iOS大全 首先如果遇到应用卡顿或者因为内存占用过多时一般使用Instruments里的来进行检测.但对于复杂情况可能就需要用到子线程监控主线程的方式来了,下面我对这些方法做些介 ...
- FIS 雪碧图sprite合并
1 安装fis(必须先安装node和npm):npm install -g fis3 2 构建项目发布到根目录下的output:fis3 release -d ./output 项目根目录:FIS3 ...
- [转]JavaScript文件操作(2)-FileReader
在上篇文章中,我介绍了在JavaScript操作文件,重点讲了如何取得File对象. 这些对象包含的文件的元数据在上传或者拖放到浏览器中时可以获取到.有了文件当然接下来就是读取文件了. FileRea ...
- SYS/BIOS实例分析
SYS/BIOS简介 SYS/BIOS是一个可扩展的实时内核(或者说是操作系统),其提供了许多模块化的APIs(应用程序接口),支持抢占式多线程,硬件抽象,实时分析和配置工具,其设计目的是为了最大限度 ...
- 【转】 Pro Android学习笔记(二九):用户界面和控制(17):include和merge
目录(?)[-] xml控件代码重用include xml控件代码重用merge 横屏和竖屏landsacpe portrait xml控件代码重用:include 如果我们定义一个控件,需要在不同的 ...
- flume入门之一:flume 安装及测试
http://flume.apache.org/ flume下载:http://mirror.bit.edu.cn/apache/flume/1.7.0/apache-flume-1.7.0-bin. ...