Codeforces Gym 100825 F. Transportation Delegation (最大流)

来源:互联网 发布:centos安装 全选 编辑:程序博客网 时间:2024/06/03 05:37

题意

总城市数量为 s ,有 r 个原料供应商, f 个工厂分处于不同的城市。每个供应商只能供应一家工厂。

共 t 个运输商,每家运输商在 ni 个城市相互间有运输路线。每个运输商只允许使用一条运输路线。

求最多多少家工厂能获得原料?

限制条件

1r,f200

r+fs600

1t1000

1nis

解题思路

最大流。建图如下:

建立超级源点和超级汇点 src 和 des 。

源点 src 向每家原料供应商连边,流量为 1 。每家工厂向汇点 des 连边,流量为 1 .

对 s 个城市建点并拆点 si, si ,每家运输商建点并拆点 ti, ti

原料供应商向对应所在城市 si 建边,每个城市 si 对其城市中的工厂建边 。

城市 si 向每个在其城市中有运输点的运输商 ti 建边,同时 tisi 建边。

titi 建边,sisi 建边。

跑一遍最大流即可。

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));}