zoukankan      html  css  js  c++  java
  • UVa 753 (二分图最大匹配) A Plug for UNIX

    题意:

    有n个插座,m个设备以及k种转化器(每种转化器视为有无限个)。

    转换器A->B可以将A类型的插头转化成B类型的插头,所以可以插在B类型的插座上。

    求最少剩多少不匹配的设备。

    分析:

    抛开转换器不讲,插头插在插座上就是一个最大二分图匹配。

    可以用最大流的算法,增加一个连接每个插头的源点s和连接每个插座的汇点t,每条弧容量都为1.

    然后求最大流量,就是二分图的最大基数匹配。

    既然有了转换器,一种插头可以用转换器转换成多种类型的插头,所以可以Floyd一次,求出每种插头可以转换成的所有的插头类型。

    然后构二分图,求最大匹配即可。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int maxn = 400 + 10;
      6 
      7 vector<string> names;
      8 int ID(const string& s)
      9 {
     10     for(int i = 0; i < names.size(); ++i)
     11         if(names[i] == s) return i;
     12     names.push_back(s);
     13     return names.size() - 1;
     14 }
     15 
     16 int n, m, k;
     17 bool d[maxn][maxn];
     18 int target[maxn], device[maxn];
     19 
     20 const int INF = 1000000000;
     21 
     22 struct Edge
     23 {
     24     int from, to, cap, flow;
     25     Edge(int u=0, int v=0, int c=0, int f=0):from(u), to(v), cap(c), flow(f) {}
     26 };
     27 
     28 struct EdmondsKarp
     29 {
     30     int n, m;
     31     vector<Edge> edges;
     32     vector<int> G[maxn];
     33     int a[maxn];
     34     int p[maxn];
     35 
     36     void Init(int n)
     37     {
     38         for(int i = 0; i < n; ++i) G[i].clear();
     39         edges.clear();
     40     }
     41 
     42     void AddEdge(int from, int to, int cap)
     43     {
     44         edges.push_back(Edge(from, to, cap, 0));
     45         edges.push_back(Edge(to, from, 0, 0));
     46         m = edges.size();
     47         G[from].push_back(m-2);
     48         G[to].push_back(m-1);
     49     }
     50 
     51     int MaxFlow(int s, int t)
     52     {
     53         int flow = 0;
     54         for(;;)
     55         {
     56             memset(a, 0, sizeof(a));
     57             queue<int> Q;
     58             Q.push(s);
     59             a[s] = INF;
     60             while(!Q.empty())
     61             {
     62                 int x = Q.front(); Q.pop();
     63                 for(int i = 0; i < G[x].size(); ++i)
     64                 {
     65                     Edge& e = edges[G[x][i]];
     66                     if(!a[e.to] && e.cap > e.flow)
     67                     {
     68                         p[e.to] = G[x][i];
     69                         a[e.to] = min(a[x], e.cap - e.flow);
     70                         Q.push(e.to);
     71                     }
     72                 }
     73                 if(a[t]) break;
     74             }
     75             if(!a[t]) break;
     76             for(int u = t; u != s; u = edges[p[u]].from)
     77             {
     78                 edges[p[u]].flow += a[u];
     79                 edges[p[u]^1].flow -= a[u];
     80             }
     81             flow += a[t];
     82         }
     83         return flow;
     84     }
     85 };
     86 
     87 EdmondsKarp g;
     88 
     89 int main()
     90 {
     91     //freopen("in.txt", "r", stdin);
     92     int T;
     93     scanf("%d", &T);
     94     while(T--)
     95     {
     96         names.clear();
     97         memset(d, 0, sizeof(d));
     98         string s1, s2;
     99         scanf("%d", &n);
    100         for(int i = 0; i < n; ++i) { cin >> s1; target[i] = ID(s1); }
    101         scanf("%d", &m);
    102         for(int i = 0; i < m; ++i) { cin >> s1 >> s2; device[i] = ID(s2); }
    103         scanf("%d", &k);
    104         for(int i = 0; i < k; ++i) { cin >> s1 >> s2; d[ID(s1)][ID(s2)] = true;    }
    105         //Floyd
    106         int V = names.size();
    107         for(int k = 0; k < V; ++k)
    108             for(int i = 0; i < V; ++i)
    109                 for(int j = 0; j < V; ++j)
    110                     d[i][j] |= d[i][k] && d[k][j];
    111 
    112         //Build Graph
    113         g.Init(V+2);
    114         for(int i = 0; i < m; ++i) g.AddEdge(V, device[i], 1);//源点到每个设备
    115         for(int i = 0; i < n; ++i) g.AddEdge(target[i], V+1, 1);//每个插座到汇点
    116         for(int i = 0; i < m; ++i)
    117             for(int j = 0; j < n; ++j)
    118                 if(d[device[i]][target[j]]) g.AddEdge(device[i], target[j], INF);
    119         int ans = g.MaxFlow(V, V+1);
    120         printf("%d
    ", m-ans);
    121         if(T) puts("");
    122     }
    123 
    124     return 0;
    125 }
    代码君

    紫书后面又介绍了一种更简单的做法,就是直接把k种转换器对应的k条弧加到图中去,然后求最大流。

    代码就不贴了,=_=||

  • 相关阅读:
    XML错误信息Referenced file contains errors (http://www.springframework.org/schema/beans/spring-beans-4.0.xsd). For more information, right click on the message in the Problems View ...
    Description Resource Path Location Type Cannot change version of project facet Dynamic Web Module to 2.3.
    maven创建web报错Cannot read lifecycle mapping metadata for artifact org.apache.maven.plugins:maven-compiler-plugin:maven-compiler-plugin:3.5.1:runtime Cause: error in opening zip file
    AJAX跨域
    JavaWeb学习总结(转载)
    JDBC学习笔记
    Java动态代理之JDK实现和CGlib实现
    (转)看懂UML类图
    spring boot配置使用fastjson
    python3下django连接mysql数据库
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4280403.html
Copyright © 2011-2022 走看看