【最大流 && 映射】POJ

来源:互联网 发布:mysql 命令行导入 编辑:程序博客网 时间:2024/06/06 01:41

Problem Description

输入n代表插排上有n个插口。接下来输入n行,每行输入一个字符串代表属于什么类型插口。
输入nn代表有nn个电器。接下来nn行,每行输入两个字符串,代表第一个字符串这个电器 可以 插到第二个字符串这种插口。
输入m代表有m种转换器,转换器个数不限,接下来输入m行,每行输入两个字符串,代表可以将第二个字符串的插口转换为第一个字符串这种插口类型。

思路:

核心就是读懂题目,问了学长题目什么意思才懂的。然后把字符串都映射成点,建图,求最大流就好了。答案是nn-最大流。

#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<map>#include<iostream>using namespace std;struct node{    int to, w, next;};node Map[50000];int head[500], vis[500], cnt;void add(int u, int v, int w)//前向星存图{    Map[cnt].to = v;    Map[cnt].w = w;    Map[cnt].next = head[u];    head[u] = cnt++;    Map[cnt].to = u;    Map[cnt].w = 0;    Map[cnt].next = head[v];    head[v] = cnt++;}int dfs(int s, int e, int f)//找增广路,找到返回限制流量,找不到返回0{    vis[s] = 1;    if(s == e) return f;    for(int i = head[s]; ~i; i = Map[i].next)    {        int to = Map[i].to, &w = Map[i].w;        if(!vis[to] && w)        {            int d = dfs(to, e, min(f, w));            if(d > 0)            {                w -= d;                Map[i^1].w += d;                return d;            }        }    }    return 0;}int ek(int s, int e)//最大流{    int Max_flow = 0, flow = 0;    for(;;)    {        memset(vis, 0, sizeof(vis));        flow = dfs(s, e, 0x3f3f3f3f);        if(flow == 0) break;        Max_flow += flow;    }    return Max_flow;}int main(){    int n, i, m, nn;    string s, str;    while(~scanf("%d", &n))    {        cnt = 0;        int top = 1;        memset(head, -1, sizeof(head));        map<string, int> q;        map<string, int>::iterator it;        for(i = 1; i <= n; i++)        {            cin >> s;            q[s] = top++;        }        scanf("%d", &nn);        for(i = 1; i <= nn; i++)        {            cin >> str >> s;            if(!q.count(str))                q[str] = top++;            if(!q.count(s))                q[s] = top++;            add(q[str], q[s], 1);//用电器和插口类型建边,流量为1            add(0, q[str], 1);//超级源点和用电器建边,流量为1        }        scanf("%d", &m);        while(m--)        {            cin >> str >> s;//转换器可以将s类型的插口变为str类型            if(!q.count(str))                q[str] = top++;            if(!q.count(s))                q[s] = top++;            add(q[str], q[s], 0x3f3f3f3f);//str类型插口和s类型插口建边,流量为无穷(无穷多个)        }        for(i = 1; i <= n; i++)        {            add(i, i+top-1, 1);//插口和插口建边,流量为1,毕竟插口只有一个            add(i+top-1, n+top, 1);//插口和超级汇点建边流量为1        }        printf("%d\n", nn - ek(0, n + top));    }    return 0;}