zoukankan      html  css  js  c++  java
  • POJ1087-A Plug for UNIX(最大流)

    题意:买了n个插座,m个电器,k个转换器。(n(1 <= n <= 100)(1 <= m <= 100)(1 <= k <= 100)),转换器会把(s1 s2)中的s2插座转换成s1插座。

    //插座个数
    4
    A
    B
    C
    D
    //插头个数
    5
    laptop B 
    phone C 
    pager B 
    clock B 
    comb X 
    //转换器种类
    3 
    B X 
    X A 
    X D
    

    分析:我们可以用map为每个插座赋值一个id,我们从源点向插座连一条容量为1的边,因为每个插座只能适配一个插头。其次,我们为每个插头也赋值一个id,从适配的插座向插头连边,容量为1。然后插头再向汇点连边。我们的交换器比如(s1 s2),表示s2的插座器可以向s1的插座器连边,容量为inf。因为交换器是无限的。

    注意:每次赋值都要判断一个类型的插座或者插头是否存在。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <map>
    #include <queue>
    #include <algorithm>
    
    using namespace std;
    
    const int inf = 1 << 29, N = 2005, M = 2 * N;
    int h[N], e[M], ne[M], d[N];
    int w[M];
    
    int s, t, idx, maxflow;
    
    void add(int a, int b, int c)
    {
    	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
    	e[idx] = a, w[idx] = 0, ne[idx] = h[b], h[b] = idx++;
    }
    
    //构造分层图
    bool bfs()
    {
    	memset(d, 0, sizeof d);
    	queue<int> q;
    	q.push(s), d[s] = 1;
    	while (q.size())
    	{
    		int u = q.front();
    		q.pop();
    		for (int i = h[u]; i != -1; i = ne[i])
    		{
    			int j = e[i];
    			if (w[i] && !d[j])
    			{
    				q.push(j);
    				d[j] = d[u] + 1;
    				if (j == t) return true;
    			}
    		}
    	}
    	return false;
    }
    
    int dinic(int u, int flow)
    {
    	if (u == t) return flow;
    	int rest = flow, k;
    	for (int i = h[u]; i != -1 && rest; i = ne[i])
    	{
    		int j = e[i];
    		if (w[i] && d[j] == d[u] + 1)
    		{
    			k = dinic(j, min(rest, w[i]));
    			if (!k) d[j] = 0;
    			w[i] -= k;
    			w[i ^ 1] += k;
    			rest -= k;
    		}
    	}
    	return flow - rest;
    }
    
    map<string, int> mp;
    
    int main()
    {	
    	memset(h, -1, sizeof h);
    	s = 0, t = 1000;
    	//插座个数
    	int n;
    	scanf("%d", &n);
    	string name, name2;
    
    	int id = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		cin >> name;
    		mp[name] = ++id;
    		//源点向插座连边
    		add(s, id, 1);
    	}
    	int m;
    	//插头个数
    	scanf("%d", &m);
    
    	for (int i = 1; i <= m; ++i)
    	{
    		//插头名和插头类型
    		cin >> name >> name2;
    		mp[name] = ++id;
    		if (mp.find(name2) == mp.end())
    		{
    			mp[name2] = ++id;
    		}
    		//插座向插头连边
    		add(mp[name2], mp[name], 1);
    		//插头向汇点连边
    		add(mp[name], t, 1);
    	}
    
    	int k;
    	scanf("%d", &k);
    	for (int i = 1; i <= k; ++i)
    	{
    		cin >> name >> name2;
    		if (mp.find(name) == mp.end())
    			mp[name] = ++id;
    		if (mp.find(name2) == mp.end())
    			mp[name2] = ++id;
    		add(mp[name2], mp[name], inf);
    	}
    
    	int flow = 0;
    	while (bfs())
    	{
    		while (flow = dinic(s, inf)) maxflow += flow;
    	}
    
    	printf("%d
    ", m - maxflow);
    
    	return 0;
    }
    
  • 相关阅读:
    滑动窗口算法-2
    滑动窗口算法-1
    工作中缓存使用重点
    QPS的计算方法[转载]
    springAop
    spring配置详述与springboot
    LRU最少使用
    图片压缩
    Javassist使用[转载]
    [转]关于Spring事务嵌套回滚的一些测试总结
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13323862.html
Copyright © 2011-2022 走看看