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\n", m-ans);

121         if(T) puts("");

122     }

123 

124     return 0;

125 }
代码君

 

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

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

你可能感兴趣的:(unix)