您的位置:首页 > 其它

Codeforces Gym 100825F Transportation Delegation (最大流)

2015-12-11 01:07 513 查看
题目大意:

就是现在有s个州, 每个州要么有工厂要么有原材料供应商或者什么都没有, 有的话只有一家

现在有t个运输公司分别提供运输服务

要求一个工厂只能匹配一个供应商,一个供应商只能供应一个工厂,且要满足一个运输公司只为其中一个匹配对服务(可以通过多个运输公司一起来传递来配对一个工厂和供应商)

问最大匹配对数

大致思路:

EC-final前最后一个题.....打完之后训练就结束了呢= =

表示这个题真是让我见识到了什么叫网络流不知道可不可以,先来一发T了再说...简直暴力出奇迹

可以考虑这么建图:

所有工厂和源点连一条容量为1的边, 然后供应商和汇点连一条容量为1的边

对于每一个运输公司,抽象出两个点p1, p2,连一条容量为1的边来控制公司只用一次

对于每一个该运输公司可以服务的点与p1连一条容量1的边, 与p2连一条容量1的边

于是跑一遍最大流就是答案了

这个图最坏情况下应该是1000*2+600+2个点

600*2*1000+1000+600条无向边(120W...)

然而网络流单组数据只跑了159ms.....好强大...

代码如下:

Result  :  Accepted     Memory  :  37712 KB     Time  :  156 ms

/*
* Author: Gatevin
* Created Time:  2015/12/11 0:11:10
* File Name: Yukinoshita_Yukino.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

#define maxn 2700

#define maxm 1202000

struct Edge
{
int u, v, nex, cap;
Edge(){}
Edge(int _u, int _v, int _nex, int _cap)
{
u = _u, v = _v, nex = _nex, cap = _cap;
}
};

Edge edge[maxm << 1];
int E;
int head[maxn];

void add_Edge(int u, int v, int c)
{
edge[++E] = Edge(u, v, head[u], c);
head[u] = E;
edge[++E] = Edge(v, u, head[v], 0);
head[v] = E;
}

int dep[maxn];

bool bfs(int start, int end)
{
int Q[maxn];
int l, r;
l = r = 0;
memset(dep, -1, sizeof(dep));
Q[r++] = start;
dep[start] = 0;
while(l != r)
{
int u = Q[l++];
if(l == maxn) l = 0;
for(int i = head[u]; i + 1; i = edge[i].nex)
{
int v = edge[i].v;
if(edge[i].cap > 0 && dep[v] == -1)
{
dep[v] = dep[u] + 1;
Q[r++] = v;
if(r >= maxn) r = 0;
if(v == end) return 1;
}
}
}
return 0;
}

int dinic(int start, int end)
{
int res = 0;
int top;
int cur[maxn];
int stack[maxn];
while(bfs(start, end))
{
memcpy(cur, head, sizeof(head));
int u = start;
top = 0;
while(1)
{
if(u == end)
{
int min = 1e9;
int loc;
for(int i = 0; i < top; i++)
if(min > edge[stack[i]].cap)
{
min = edge[stack[i]].cap;
loc = i;
}
for(int i = 0; i < top; i++)
{
edge[stack[i]].cap -= min;
edge[stack[i] ^ 1].cap += min;
}
res += min;
top = loc;
u = edge[stack[top]].u;
}
for(int i = cur[u]; i + 1; cur[u] = i = edge[i].nex)
if(edge[i].cap != 0 && dep[u] + 1 == dep[edge[i].v])
break;
if(cur[u] != -1)
{
stack[top++] = cur[u];
u = edge[cur[u]].v;
}
else
{
if(top == 0) break;
dep[u] = -1;
u = edge[stack[--top]].u;
}
}
}
return res;
}

map<string, int> M;

int main()
{
ios::sync_with_stdio(0);
E = -1;
memset(head, -1, sizeof(head));
int s, r, f, t;
cin>>s>>r>>f>>t;
string name;
int S = 0, T = s + 2*t + 1;
int cnt = 0;
for(int i = 0; i < r; i++)
{
cin>>name;
if(M.count(name) == 0)
{
M[name] = ++cnt;
add_Edge(S, cnt, 1);
}
}
for(int i = r + 1; i <= r + f; i++)
{
cin>>name;
if(M.count(name) == 0)
{
M[name] = ++cnt;
add_Edge(cnt, T, 1);
}
}
for(int i = 1; i <= t; i++)
{
int x;
cin>>x;
int point1 = ++cnt, point2 = ++cnt;
add_Edge(point1, point2, 1);
while(x--)
{
cin>>name;
if(M.count(name) == 0)
M[name] = ++cnt;
int num = M[name];
add_Edge(num, point1, 1);
add_Edge(point2, num, 1);
}
}
cout<<dinic(S, T)<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息