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 ...
随机推荐
- 使用pjsip传输已经编码的视频,源码在github
pjsip功能很强,做sip rtp语音通话库首选.在2.0之后,也支持视频.不过,它的视频功能缺省是从视频设备采集,然后进行编译,再发送出去的.假设,我们已经有了视频源,比如IP摄像机,不需要采集和 ...
- 关于对H264码流的PS的封装的相关代码实现
1.写在开始之前: 最近因为新工作要维护别人留下的GB模块代码,先熟悉了流程,然后也试着封装了下ps流,结果也能通过测试正常预览了,当然,其中开发读文档的头疼,预览花屏,卡帧的事情都有遇到,当时慢慢的 ...
- [冬令营模拟]GTSG2018
上学期没有去 GTSG,于是今天老师让我们来做一下 GTSG2018 Day1 & Day3 Day1 在上午当成一场考试来搞了,Day3 由于锅太多而且 T3 玄学而被放到下午自学... 上 ...
- 用Raspberry Pi搭建Azure IOT解决方案
Raspberry Pi是一款基于Linux的单板机电脑.它由英国的树莓派基金会所开发,目的是以低价硬件及自由软件刺激在学校的基本计算机科学教育.树莓派配备一枚博通(Broadcom)出产的ARM架构 ...
- CCS V5 使用教程一: 安装激活与创建工程
CCS下载与安装 下载地址 Liscense下载地址 安装教程 创建工程 工程创建教程
- 【转】Pro Android学习笔记(二四):用户界面和控制(12):Style和Theme
目录(?)[-] 静态格式 代码中设定 Style Theme 静态格式 在res/values中设置静态的Style,在资源中设置静态Style可使用的HTML格式有<i> <u& ...
- 杂项-Log:log4net
ylbtech-杂项-Log:log4net log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台.文件.数据库等) ...
- 阻止文件不被上传到iCloud
转自:http://blog.csdn.net/a921800467b/article/details/38386787 http://www.cocoachina.com/bbs/read.php? ...
- uboot启动参数设置分类及方法
一.nfs启动内核与根文件系统,内核与根文件系统都在nfs上 bootargs=noinitrd root=/dev/nfs rw nfsroot=192.168.0.1:/home/tekkaman ...
- java基础知识(5)---继承
继 承:(面向对象特征之一)好处:1:提高了代码的复用性.2:让类与类之间产生了关系,提供了另一个特征多态的前提. 父类的由来:其实是由多个类不断向上抽取共性内容而来的.java中对于继承,java只 ...