题意
总城市数量为 s ,有 r 个原料供应商, f 个工厂分处于不同的城市。每个供应商只能供应一家工厂。
共 t 个运输商,每家运输商在 ni 个城市相互间有运输路线。每个运输商只允许使用一条运输路线。
求最多多少家工厂能获得原料?
限制条件
1≤r,f≤200
r+f≤s≤600
1≤t≤1000
1≤ni≤s
解题思路
最大流。建图如下:
建立超级源点和超级汇点 src 和 des 。
源点 src 向每家原料供应商连边,流量为 1 。每家工厂向汇点 des 连边,流量为 1 .
对 s 个城市建点并拆点 si, s′i ,每家运输商建点并拆点 ti, t′i 。
原料供应商向对应所在城市 si 建边,每个城市 s′i 对其城市中的工厂建边 。
城市 si 向每个在其城市中有运输点的运输商 ti 建边,同时 t′i 向 s′i 建边。
ti 向 t′i 建边, s′i 向 si 建边。
跑一遍最大流即可。
HINT:所有为提及的边流量均为 1 .
代码
#include<bits/stdc++.h>
using namespace std;
int s, r, f, t, idx, src, des, n;
string str, path[610];
map<string, int> mp;
const int inf = 1e9 + 7; //预设最大值
const int maxv = 4000 + 10; //最大点数
struct Edge {
int to,cap,rev;
Edge(){};
Edge(int _to,int _cap,int _rev) {
to = _to; cap = _cap; rev = _rev;
}
};
vector<Edge> G[maxv];
int level[maxv];
int iter[maxv];
void init() {
for(int i=0;i<maxv;i++)
G[i].clear();
}
void addedge(int from,int to,int cap) { //加边,from->to单向边,反向边为0
G[from].push_back(Edge(to, cap, G[to].size()));
G[to].push_back(Edge(from, 0, G[from].size()-1));
}
void bfs(int s) {
memset(level,-1,sizeof(level));
queue<int> que;
level[s] = 0;
que.push(s);
while(!que.empty()) {
int v = que.front();
que.pop();
for(int i=0;i<G[v].size();i++) {
Edge &e = G[v][i];
if(e.cap > 0 && level[e.to] < 0) {
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
}
int dfs(int v,int t,int f) {
if(v == t) return f;
for(int &i=iter[v];i < G[v].size();i++) {
Edge &e = G[v][i];
if(e.cap > 0 && level[v] < level[e.to]) {
int d = dfs(e.to,t,min(f,e.cap));
if(d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int maxflow(int s,int t) { //s、t分别为源点、汇点
int flow = 0;
while(true) {
bfs(s);
if(level[t] < 0) return flow;
memset(iter,0,sizeof(iter));
int f;
while((f = dfs(s,t,inf)) > 0)
flow += f;
}
}
int main()
{
scanf("%d %d %d %d", &s, &r, &f, &t);
src = 0, des = s*3 + 2*t + 1;
for(int i=0;i<r;i++)
{
cin>>str;
mp[str] = ++idx;
addedge(src, mp[str], 1);
addedge(mp[str], mp[str]+s, 1);
}
for(int i=0;i<f;i++)
{
cin>>str;
mp[str] = ++idx;
addedge(mp[str], des, 1);
addedge(mp[str]+2*s, mp[str], 1);
}
for(int i=1;i<=t;i++)
{
scanf("%d", &n);
for(int j=1;j<=n;j++)
{
cin>>path[j];
if(mp.find(path[j]) == mp.end())
mp[path[j]] = ++idx;
}
for(int j=1;j<=n;j++)
{
addedge(mp[path[j]] + s, 3*s+i, 1);
addedge(3*s+i+t, mp[path[j]] + 2*s, 1);
}
addedge(3*s+i, 3*s+i+t, 1);
}
for(int i=1;i<=s;i++)
addedge(2*s+i, s+i, 1);
printf("%d\n", maxflow(src, des));
}