Google Code Jam 2015 R2 C
题意:给出若干个句子,每个句子包含多个单词。确定第一句是英文,第二句是法文。后面的句子两者都有可能。两个语种会有重复单词。
现在要找出一种分配方法(给每个句子指定其文种),使得既是英文也是法文的单词数量最少。
分析:网络流的最小割。
建图方法如下,每个句子一个点。每个单词一个点。句子向其所属的单词连双向无穷流量边。把第一个句子作为起点,第二句作为终点。
现在我们要割掉一些单词,使得起点无法到达终点。
图的意义是这样的。如果我们能找到一条从起点到达终点的通路,那么中间一定有一个过程是从一个英文句子跳到一个单词,然后跳到一个法文句子。这就说明该单词既是英文又是法文。
而如果找不到通路,把所有能到达的句子点归为英文,其余的归为法文。这样就成功地完成了划分任务,而没有同属于两个语言的单词。
所以,割掉单词使得图没有通路就是一种划分的充要条件。
割点的方法就是拆点,每个单词拆成两点,一个负责入边,一个负责出边。中间加一条流量为1的边。
本题还有一个难点就是输入,每个句子要自己根据空格划分成单词。
stringstream可以将字符串作为输入流,从中读入内容。用stringstream sin(inputstring); 之后读入方法与cin一样。需要包含sstream头文件。
char*转化成string可以直接用等号赋值。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
#include <string>
#include <sstream>
using namespace std; #define D(x) const int MAX_N = ;
const int MAX_DIC = ;
const int MAX_WORD_NUM = ; const int MAX_NODE_NUM = (MAX_N * + ) * + MAX_N;
const int MAX_EDGE_NUM = (int)(1e6);
#define INF 0x3f3f3f3f struct Edge
{
int next, v, f;
Edge()
{}
Edge(int next, int v, int f):next(next), v(v), f(f)
{}
} edge[MAX_EDGE_NUM * ]; int head[MAX_NODE_NUM];
int q[MAX_NODE_NUM];
bool vis[MAX_NODE_NUM];
int cur[MAX_NODE_NUM];
int dep[MAX_NODE_NUM];
int edge_cnt;
int path[MAX_NODE_NUM];
int front, rear, q_size; void add_edge(int u, int v, int f)
{
edge[edge_cnt] = Edge(head[u], v, f);
head[u] = edge_cnt++;
edge[edge_cnt] = Edge(head[v], u, );
head[v] = edge_cnt++;
} void init()
{
edge_cnt = ;
memset(head, -, sizeof(head));
} void q_init(int size)
{
front = ;
rear = ;
q_size = size;
} void q_push(int a)
{
q[rear++] = a;
rear %= q_size;
} int q_pop()
{
int ret = q[front++];
front %= q_size;
return ret;
} void bfs(int s, int t)
{
memset(vis, , sizeof(vis));
memset(dep, -, sizeof(dep));
q_init(MAX_NODE_NUM);
q_push(s);
vis[s] = true;
dep[s] = ;
while (front != rear && !vis[t])
{
int u = q_pop();
for (int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if (!vis[v] && edge[i].f > )
{
q_push(v);
vis[v] = true;
dep[v] = dep[u] + ;
}
}
}
} int add_flow(int path[], int &path_n)
{
int min_edge = -, delta = INF;
for (int i = ; i < path_n; ++i)
{
if (edge[path[i]].f < delta)
{
delta = edge[path[i]].f;
min_edge = i;
}
}
for (int i = ; i < path_n; ++i)
{
edge[path[i]].f -= delta;
edge[path[i] ^ ].f += delta;
}
path_n = min_edge;
return delta;
} int last_node(int path[], int path_n, int s)
{
if (path_n)
return edge[path[path_n - ]].v;
return s;
} int find_next(int start)
{
for (int e = cur[start]; ~e; e = edge[e].next)
if (edge[e].f && dep[start] + == dep[edge[e].v])
return e;
return -;
} int dfs(int s, int t)
{
int ret = ;
int path_n = ;
int x = s;
memcpy(cur, head, sizeof(cur));
while (true)
{
if (x == t)
{
ret += add_flow(path, path_n);
x = last_node(path, path_n, s);
}
int next_edge = find_next(x);
cur[x] = next_edge;
if (next_edge == -)
{
if (path_n == )
break;
dep[x] = -;
--path_n;
x = last_node(path, path_n, s);
continue;
}
path[path_n++] = next_edge;
x = edge[next_edge].v;
}
return ret;
} int dinic(int s, int t)
{
int ret = ;
while (true)
{
bfs(s, t);
if (dep[t] == -)
return ret;
ret += dfs(s, t);
}
return -;
} int n;
map<string, int> dictionary;
vector<string> word[MAX_N]; void input()
{
dictionary.clear();
scanf("%d", &n);
getchar();
for (int i = ; i < n; i++)
{
word[i].clear();
char st[MAX_DIC * MAX_WORD_NUM];
fgets(st, MAX_DIC * MAX_WORD_NUM, stdin);
string s = st;
stringstream sin(s);
while (sin >> s)
{
if (dictionary.find(s) == dictionary.end())
dictionary[s] = dictionary.size() - ;
word[i].push_back(s);
}
}
} int work()
{
init();
for (int i = ; i < (int)dictionary.size(); i++)
{
int id1 = i * + n;
int id2 = id1 + ;
add_edge(id1, id2, );
}
for (int i = ; i < n; i++)
{
for (int j = ; j < (int)word[i].size(); j++)
{
int id = dictionary[word[i][j]];
int id1 = id * + n;
int id2 = id1 + ;
add_edge(i, id1, INF);
add_edge(id2, i, INF);
}
}
return dinic(, );
} int main()
{
int t;
scanf("%d", &t);
int case_num = ;
while (t--)
{
case_num++;
printf("Case #%d: ", case_num);
input();
printf("%d\n", work());
bfs(, );
}
return ;
}
Google Code Jam 2015 R2 C的更多相关文章
- Google Code Jam 2015 R1C B
题意:给出一个键盘,按键都是大写字母.给出一个目标单词和一个长度L.最大值或者最大长度都是100.现在随机按键盘,每个按键的概率相同. 敲击出一个长度为L的序列.求该序列中目标单词最多可能出现几次,期 ...
- Google Code Jam 2015 Round1A 题解
快一年没有做题了, 今天跟了一下 GCJ Round 1A的题目, 感觉难度偏简单了, 很快搞定了第一题, 第二题二分稍微考了一下, 还剩下一个多小时, 没仔细想第三题, 以为 前两个题目差不多可以晋 ...
- [C++]Infinite House of Pancakes——Google Code Jam 2015 Qualification Round
Problem It’s opening night at the opera, and your friend is the prima donna (the lead female singer) ...
- [C++]Standing Ovation——Google Code Jam 2015 Qualification Round
Problem It’s opening night at the opera, and your friend is the prima donna (the lead female singer) ...
- Google Code Jam 2010 Round 1C Problem A. Rope Intranet
Google Code Jam 2010 Round 1C Problem A. Rope Intranet https://code.google.com/codejam/contest/61910 ...
- [Google Code Jam (Qualification Round 2014) ] B. Cookie Clicker Alpha
Problem B. Cookie Clicker Alpha Introduction Cookie Clicker is a Javascript game by Orteil, where ...
- [Google Code Jam (Qualification Round 2014) ] A. Magic Trick
Problem A. Magic Trick Small input6 points You have solved this input set. Note: To advance to the ...
- [C++]Store Credit——Google Code Jam Qualification Round Africa 2010
Google Code Jam Qualification Round Africa 2010 的第一题,很简单. Problem You receive a credit C at a local ...
- [C++]Saving the Universe——Google Code Jam Qualification Round 2008
Google Code Jam 2008 资格赛的第一题:Saving the Universe. 问题描述如下: Problem The urban legend goes that if you ...
随机推荐
- python快排算法
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. ...
- Yii2.0高级框架数据库增删改查的一些操作(转)
yii2.0框架是PHP开发的一个比较高效率的框架,集合了作者的大量心血,下面通过用户为例给大家详解yii2.0高级框架数据库增删改查的一些操作 --------------------------- ...
- 繁华模拟赛day8 字典序
/* 这个题要我们求一个字典序,字符串给出的顺序,会对字母的字典序前后相对顺序进行限定,如何用来表示这种限定,我们注意到这种一个之后接着一个,只有先输出他前面的才能输出他,很明显就是拓扑排序,最小方案 ...
- 用Javascript获取页面元素的位置
制作网页的过程中,你有时候需要知道某个元素在网页上的确切位置. 下面的教程总结了Javascript在网页定位方面的相关知识. 一.网页的大小和浏览器窗口的大小 首先,要明确两个基本概念. 一张网页的 ...
- Memcached原理分析
Memcached的内存管理方式 Memcached采用了名为Slab Allocation的机制分配,管理内存. Slab Allocation的原理相当简单.将分配的内存分割成各种尺寸的块(chu ...
- ajax如何返回多个值
应用场景: 在前端有个ajax请求到后端后,需要返回多个变量的值,在这里使用的是Json格式作为值传递,使用eval函数来解析Json格式. 要传递的值data: var data = " ...
- 大数据之pig 命令
1.pig与hive的区别 pig和hive比较类似的,都是类sql的语言,底层都是依赖于hadoop 走的mapreduce任务. pig和hive的区别就是,想要实现一个业务逻辑的话, ...
- Android4.4 往短信收件箱中插入自定义短信(伪造短信)
这段时间稍微有点空闲,把前一段学习Android做过的一些小项目整理整理.虽然没有什么工程量很大的项目,但是对于一个新手,解决这些问题还是花了一段时间.感觉还是非常有记录的意义呢~~~么么哒*—* 今 ...
- (二)js下拉菜单
默认的select标签比较难看,UI比较漂亮,如果想要实现UI上的下拉样式,好像必须用js写select,从网上拷贝而且修改了一个下拉框,为了方便以后引用所以记录下来. /* diy_select * ...
- iOS开发——多线程篇——RunLoop
一.简介 1.什么是RunLoop从字面意思看运行循环跑圈 基本作用保持程序的持续运行处理App中的各种事件(比如触摸事件.定时器事件.Selector事件)节省CPU资源,提高程序性能:该做事时做事 ...