您的位置:首页 > 编程语言 > Go语言

Google Code Jam 2015 R2 C

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

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

分析:网络流的最小割。

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

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

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

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

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

割点的方法就是拆点,每个单词拆成两点,一个负责入边,一个负责出边。中间加一条流量为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 = 300;
const int MAX_DIC = 1010;
const int MAX_WORD_NUM = 20;

const int MAX_NODE_NUM = (MAX_N * 10 + 2000) * 2 + 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 * 2];

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, 0);
head[v] = edge_cnt++;
}

void init()
{
edge_cnt = 0;
memset(head, -1, sizeof(head));
}

void q_init(int size)
{
front = 0;
rear = 0;
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, 0, sizeof(vis));
memset(dep, -1, sizeof(dep));
q_init(MAX_NODE_NUM);
q_push(s);
vis[s] = true;
dep[s] = 0;
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 > 0)
{
q_push(v);
vis[v] = true;
dep[v] = dep[u] + 1;
}
}
}
}

int add_flow(int path[], int &path_n)
{
int min_edge = -1, delta = INF;
for (int i = 0; i < path_n; ++i)
{
if (edge[path[i]].f < delta)
{
delta = edge[path[i]].f;
min_edge = i;
}
}
for (int i = 0; i < path_n; ++i)
{
edge[path[i]].f -= delta;
edge[path[i] ^ 1].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 - 1]].v;
return s;
}

int find_next(int start)
{
for (int e = cur[start]; ~e; e = edge[e].next)
if (edge[e].f && dep[start] + 1 == dep[edge[e].v])
return e;
return -1;
}

int dfs(int s, int t)
{
int ret = 0;
int path_n = 0;
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 == -1)
{
if (path_n == 0)
break;
dep[x] = -1;
--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 = 0;
while (true)
{
bfs(s, t);
if (dep[t] == -1)
return ret;
ret += dfs(s, t);
}
return -1;
}

int n;
map<string, int> dictionary;
vector<string> word[MAX_N];

void input()
{
dictionary.clear();
scanf("%d", &n);
getchar();
for (int i = 0; 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() - 1;
word[i].push_back(s);
}
}
}

int work()
{
init();
for (int i = 0; i < (int)dictionary.size(); i++)
{
int id1 = i * 2 + n;
int id2 = id1 + 1;
add_edge(id1, id2, 1);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < (int)word[i].size(); j++)
{
int id = dictionary[word[i][j]];
int id1 = id * 2 + n;
int id2 = id1 + 1;
add_edge(i, id1, INF);
add_edge(id2, i, INF);
}
}
return dinic(0, 1);
}

int main()
{
int t;
scanf("%d", &t);
int case_num = 0;
while (t--)
{
case_num++;
printf("Case #%d: ", case_num);
input();
printf("%d\n", work());
bfs(0, 1);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: