POJ 1087 A Plug for UNIX(网络流模板题)

谜一样的题意的题目,我真的是!@#¥%……&*(。

题意就是说,我有n个插头,m个电器,k个转换器和插头之间的组合(类似于交换机?),比如样例中的B X,就说明B可以把接受到的全部流量转移到X中,然后X A,说明X中的全部流量可以转移到A上。但是,我们只有n个插头,只有插头才可以接电源充电。m个电器也有相对应能用的插头,比如样例的phone是不能用B插头的,只能用C。

然后,套用一下网络流EK模版,搞定。下面的数组至少要开300 * 300的貌似,200会RE,估计他的k个数据里面又偷偷引入了一堆新的插头或者转换器什么的。


#include<iostream>
#include<queue>
#include<cstring> 
#include<map>
#include<cstdio>
using namespace std;
const int maxn = 305;
const int INF = 0x7fffffff;
int r[maxn][maxn];
bool visit[maxn];
int pre[maxn];
int cnt = 1;

bool bfs(int s, int t)
{
    int p;
    queue <int> q;
    memset(pre, -1, sizeof(pre));
    memset(visit, false, sizeof(visit));
    pre[s] = s;
    visit[s] = true;
    q.push(s);
    while(!q.empty())
    {
        p = q.front();
        q.pop();
        for(int i = 0; i <= cnt; i++)
        {
            if(r[p][i] > 0 && !visit[i])
            {
                pre[i] = p;
                visit[i] = true;
                if(i == t) 
					return true;
                q.push(i);
            }
        }
    }
    return false;
}

int EdmondsKarp(int s,int e)
{
   	int flow = 0, d, i;
   	while(bfs(s, e))
   	{
       	d = INF;
       	for(i = e; i != s; i = pre[i])
           d = d < r[pre[i]][i] ? d : r[pre[i]][i];
       	for(i = e; i != s; i = pre[i])
       	{
           r[pre[i]][i] -= d;
           r[i][pre[i]] += d;
       	}
       flow += d;
   }
   return flow;
}

int main()
{
    int u, v, w;
    int m, n, k;
    map <string, int> devices, receptacles, adapters;
	map <string, int>::iterator iter; 
    char str1[30], str2[30];
    memset(r, 0, sizeof(r));
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
    {
    	scanf("%s", str1);
    	receptacles[str1] = cnt++;
	}
	scanf("%d", &m);
    for(int i = 0; i < m; i++)
    {
        scanf("%s%s", &str1, &str2);
        if(devices.find(str1) == devices.end())
        {
        	u = cnt;
        	devices[str1] = cnt++;
        }
        else
        	u = devices[str1];
        if(receptacles.find(str2) == receptacles.end())
        {
        	v = cnt;
        	adapters[str2] = cnt++;
        }
        else
        	v = receptacles[str2];
        r[u][v] = 1;
    }
    scanf("%d", &k);
    for(int i = 0; i < k; i++)
    {
    	scanf("%s%s", &str1, &str2);
    	if(receptacles.find(str1) != receptacles.end())
        	u = receptacles[str1];
        else
        	u = adapters[str1];
        
        if(receptacles.find(str2) != receptacles.end())
        	v = receptacles[str2];
        else
        	v = adapters[str2];
        r[u][v] = INF;
	}
	for(iter = devices.begin(); iter != devices.end(); iter++)
		r[0][iter->second] = 1;
	for(iter = receptacles.begin(); iter != receptacles.end(); iter++)
		r[iter->second][cnt] = 1;
    printf("%d\n", m - EdmondsKarp(0, cnt));
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值