题意:给出若干个句子,每个句子包含多个单词。确定第一句是英文,第二句是法文。后面的句子两者都有可能。两个语种会有重复单词。

现在要找出一种分配方法(给每个句子指定其文种),使得既是英文也是法文的单词数量最少。

分析:网络流的最小割。

建图方法如下,每个句子一个点。每个单词一个点。句子向其所属的单词连双向无穷流量边。把第一个句子作为起点,第二句作为终点。

现在我们要割掉一些单词,使得起点无法到达终点。

图的意义是这样的。如果我们能找到一条从起点到达终点的通路,那么中间一定有一个过程是从一个英文句子跳到一个单词,然后跳到一个法文句子。这就说明该单词既是英文又是法文。

而如果找不到通路,把所有能到达的句子点归为英文,其余的归为法文。这样就成功地完成了划分任务,而没有同属于两个语言的单词。

所以,割掉单词使得图没有通路就是一种划分的充要条件。

割点的方法就是拆点,每个单词拆成两点,一个负责入边,一个负责出边。中间加一条流量为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的更多相关文章

  1. Google Code Jam 2015 R1C B

    题意:给出一个键盘,按键都是大写字母.给出一个目标单词和一个长度L.最大值或者最大长度都是100.现在随机按键盘,每个按键的概率相同. 敲击出一个长度为L的序列.求该序列中目标单词最多可能出现几次,期 ...

  2. Google Code Jam 2015 Round1A 题解

    快一年没有做题了, 今天跟了一下 GCJ Round 1A的题目, 感觉难度偏简单了, 很快搞定了第一题, 第二题二分稍微考了一下, 还剩下一个多小时, 没仔细想第三题, 以为 前两个题目差不多可以晋 ...

  3. [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) ...

  4. [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) ...

  5. 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 ...

  6. [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 ...

  7. [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 ...

  8. [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 ...

  9. [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 ...

随机推荐

  1. Storm:最火的流式处理框架

    伴随着信息科技日新月异的发展,信息呈现出爆发式的膨胀,人们获取信息的途径也更加多样.更加便捷,同时对于信息的时效性要求也越来越高.举个搜索场景中的例子,当一个卖家发布了一条宝贝信息时,他希望的当然是这 ...

  2. “Transaction rolled back because it has been marked as rollback-only”

    spring的声明事务提供了强大功能,让我们把业务关注和非业务关注的东西又分离开了.好东西的使用,总是需要有代价的.使用声明事务的时候,一 个不小心经常会碰到“Transaction rolled b ...

  3. MySQL索引之前缀索引和索引选择性

    有时需要索引很长的字符列,它会使索引变大而且变慢.一个策略就是模拟哈希索引.但是有时这也不够好,那? 通常可以索引开始的几个字符,而不是全部值,以节约空间并得到好的性能.这使索引需要的空间变小,但是也 ...

  4. IIS 您要访问的网页有问题,无法显示!

    提示:您要访问的网页有问题,无法显示.HTTP 500 – 内部服务器错误.”的问题解决方案! IIS服务器出现错误的原因很多,请尝试以下操作:1.查看网站属性——文档看看启用默认文档中是否存在:in ...

  5. ggplot2 上篇

    title: "ggplot2 上篇" author: "li_volleyball" date: "2016年4月16日" output: ...

  6. 一段可以使用的 hibernate获得对象->action存入List->jsp页面用<s:iterator>迭代的代码

    SelectAction.java @SuppressWarnings("serial") @Component("selectAction") @Scope( ...

  7. 微信电脑版真的要来了 微信Windows版客户端1.0 Alpha推出

    微信电脑版的搜索量一直很大,但只有网页版,之前也写了微信网页版APP - 网页微信客户端电脑版体验,在键盘上打字的感觉就是快.现在微信Windows版客户端1.0 Alpha推出了,来一睹芳容吧(20 ...

  8. 北京程序员 VS 硅谷程序员(转)

    夫妻双码农,北京 or 硅谷,值得吗? http://mp.weixin.qq.com/s?__biz=MzA5MzE4MjgyMw==&mid=401228574&idx=1& ...

  9. Logistic 回归(sigmoid函数,手机的评价,梯度上升,批处理梯度,随机梯度,从疝气病症预测病马的死亡率

    (手机的颜色,大小,用户体验来加权统计总体的值)极大似然估计MLE 1.Logistic回归 Logistic regression (逻辑回归),是一种分类方法,用于二分类问题(即输出只有两种).如 ...

  10. Ubuntu 12 修改当前用户密码:new password is too simple

    修改当前登录用户的密码,通常使用如下命令: $ passwd Old password:****** New password:******* Re-enter new password:****** ...