GCJ 2015R2(Bilingual-最小割)

Problem C. Bilingual

Problem

Elliot‘s parents speak French and English to him at home. He has heard a lot of words, but it isn‘t always clear to him which word comes from which language! Elliot knows one sentence that he‘s sure is English and one sentence that he‘s sure is French, and
some other sentences that could be either English or French. If a word appears in an English sentence, it must be a word in English. If a word appears in a French sentence, it must be a word in French.

Considering all the sentences that Elliot has heard, what is the minimum possible number of words that he‘s heard that must be words in both English and French?

Input

The first line of the input gives the number of test cases, TT test cases follow. Each starts with a single line containing an integer NN lines follow, each of which contains a series
of space-separated "words". Each "word" is made up only of lowercase characters a-z. The first of those N lines is a "sentence" in English, and the second is a "sentence" in French. The rest could be "sentences" in either English or French.
(Note that the "words" and "sentences" are not guaranteed to be valid in any real language.)

Output

For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the minimum number of words that Elliot has heard that must be words in both English and French.

Limits

1 ≤ T ≤ 25.

Each word will contain no more than 10 characters.

The two "known" sentences will contain no more than 1000 words each.

The "unknown" sentences will contain no more than 10 words each.

Small dataset

2 ≤ N ≤ 20.

Large dataset

2 ≤ N ≤ 200.

Sample

Input

Output

4
2
he loves to eat baguettes
il aime manger des baguettes
4
a b c d e
f g h i j
a b c i j
f g h d e
4
he drove into a cul de sac
elle a conduit sa voiture
il a conduit dans un cul de sac
il mange pendant que il conduit sa voiture
6
adieu joie de vivre je ne regrette rien
adieu joie de vivre je ne regrette rien
a b c d e
f g h i j
a b c i j
f g h d e
Case #1: 1
Case #2: 4
Case #3: 3
Case #4: 8

In Case #1, Elliot knows for sure that the first sentence is in English and the second is in French, so there is no ambiguity; the only word that must be in both English and French is "baguettes".

In Case #2, the last two sentences could either be: English English, English French, French English, or French French. The second of those possibilities is the one that minimizes the number of words common to both languages; that set turns out to be d, e, i,
and j.

最小割

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<map>
#include<string>
#include<vector>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXT (25+10)
#define MAXLen (1000*11+10)
#define MAXWord1 (1000+10)
#define MAXWord2 (10)
#define MAXTotword (2000+10*200+10)
#define MAXn (200+10)
#define MAXm (200000+10)
#define MAXN (1000000+2)
#define MAXM ((1000000+2)*2+100)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
class Max_flow  //dinic+当前弧优化
{
public:
    int n,s,t;
    int q[MAXN];
    int edge[MAXM],next[MAXM],pre[MAXN],weight[MAXM],size;
    void addedge(int u,int v,int w)
    {
        edge[++size]=v;
        weight[size]=w;
        next[size]=pre[u];
        pre[u]=size;
    }
    void addedge2(int u,int v,int w){addedge(u,v,w),addedge(v,u,0);}
    bool b[MAXN];
    int d[MAXN];
    bool SPFA(int s,int t)
    {
        For(i,n) d[i]=INF;
        MEM(b)
        d[q[1]=s]=0;b[s]=1;
        int head=1,tail=1;
        while (head<=tail)
        {
            int now=q[head++];
            Forp(now)
            {
                int &v=edge[p];
                if (weight[p]&&!b[v])
                {
                    d[v]=d[now]+1;
                    b[v]=1,q[++tail]=v;
                }
            }
        }
        return b[t];
    }
    int iter[MAXN];
    int dfs(int x,int f)
    {
        if (x==t) return f;
        Forpiter(x)
        {
            int v=edge[p];
            if (weight[p]&&d[x]<d[v])
            {
                  int nowflow=dfs(v,min(weight[p],f));
                  if (nowflow)
                  {
                    weight[p]-=nowflow;
                    weight[p^1]+=nowflow;
                    return nowflow;
                  }
            }
        }
        return 0;
    }
    int max_flow(int s,int t)
    {
        int flow=0;
        while(SPFA(s,t))
        {
            For(i,n) iter[i]=pre[i];
            int f;
            while (f=dfs(s,INF))
                flow+=f;
        }
        return flow;
    }
    void mem(int n,int s,int t)
    {
        (*this).n=n;
        (*this).t=t;
        (*this).s=s;    

        size=1;
        MEM(pre)
    }
}S;    

int T,n;

vector<string> split(string s,string del = " \n\0") // 以在del出现过的任何字符为分隔符
{
	vector<string> ret;
	s+=del[0];

	string p="";
	int sz=s.size();
	Rep(i,sz)
	{
		if (del.find(s[i])==string::npos)
		{
			p+=s[i];
		}
		else
		{
			if (p!="")
			{
				ret.push_back(p);
				p="";
			}
		}
	}
	return ret;
}

vector<string> get_line_words() {
	static string buf;
	getline(cin,buf,'\n');
	return split(buf);
}

map<string,int> h;
int get_id(string s)
{
	map<string,int>::iterator it=h.find(s);
	if (it==h.end()) return h[s]=h.size();
	return it->second;
}

vector<string> a[MAXn];
int a2[MAXn][MAXWord1];
int main()
{
	freopen("gcj2015R2CC-large-practice.in","r",stdin);
	freopen("gcj2015R2CC-large-practice.out","w",stdout);

	cin>>T;
	For(kcase,T)
	{
		h.clear();
		scanf("%d\n",&n);
		For(i,n)
		{
			string s;
			a[i]=get_line_words();
			a2[i][0]=a[i].size();
			Rep(j,a2[i][0])
				a2[i][j+1]=get_id(a[i][j]);

		}
//
//		For(i,n)
//		{
//			For(j,a2[i][0]) cout<<a2[i][j]<<' ';
//			cout<<endl;
//
//		}
//		

		int m = h.size(),s=1,t=2*m+n;
		S.mem(t,s,t);

		For(i,m)
		{
			S.addedge2(i+1,i+1+m,1);
		}

		For(j,a2[1][0]) {
			S.addedge2(s,1+a2[1][j],INF);
		}
		For(j,a2[2][0]) {
			S.addedge2(1+a2[2][j]+m,t,INF);
		}

		Fork(i,3,n)
		{
			For(j,a2[i][0]) {
				S.addedge2(2*m+1+i-2,1+a2[i][j],INF);
				S.addedge2(1+a2[i][j]+m,2*m+1+i-2,INF);
			}
		}

		int ans=S.max_flow(s,t);
		printf("Case #%d: %d\n",kcase,ans);
	}

	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-30 16:24:00

GCJ 2015R2(Bilingual-最小割)的相关文章

【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]

人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得

hdoj 4289 Control 【拆点 求最小割】

Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2295    Accepted Submission(s): 961 Problem Description You, the head of Department of Security, recently received a top-secret informati

There is a war (hdu 2435 最小割+枚举)

There is a war Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 970    Accepted Submission(s): 277 Problem Description There is a sea. There are N islands in the sea. There are some directional

HDU 3657 Game(取数 最小割)经典

Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1065    Accepted Submission(s): 449 Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each g

POJ2914 Minimum Cut【全局最小割】【Stoer-Wangner】

题目链接: http://poj.org/problem?id=2914 题目大意: 提一个无向有重边的图,有重边的边权累加起来,求全局最小割. 思路: 一个无向连通图,去掉一个边集可以使其变成两个连通分量则这个边集就是割集.最小割 集当然就是权和最小的割集. 这是一个最简单的全局最小割模板题.直接套上模板就可以了.来说说Stoer-Wangner算 法吧. Stoer-Wangner算法: 对于图中的任意两个顶点u和v,若u,v属于最小割的同一个集合中,那么僵顶点u和顶点 v合并后并不影响图的

HDU 3035 War(对偶图求最小割)

HDU 3035 War 题目链接 题意:根据图那样,给定一个网络,要求阻断s到t,需要炸边的最小代价 思路:显然的最小割,但是也显然的直接建图强行网络流会超时,这题要利用平面图求最小割的方法,把每一块当成一个点,共有边连边,然后每一个路径就是一个割,然后最短路就是最小割了 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace s

ZOJ 2587 Unique Attack 判断最小割是否唯一

很裸的判断最小割是否唯一.判断方法是先做一遍最大流求最小割,然后从源点和汇点分别遍历所有能够到达的点,看是否覆盖了所有的点,如果覆盖了所有的点,那就是唯一的,否则就是不唯一的. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostr

AHOI2009最小割

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1072  Solved: 446[Submit][Status] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案,使中转站s不能到

bzoj1412-网络流最小割

狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆.可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已.所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养. 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变