这还是一道典型的network maxflow问题。所以基本和上道题的代码一样。这里需要构造一个source和一个sink。 从source到每只牛构造一条capacity为1的路径,从每只poll到sink构造一条capacity为1的路径。相应地把牛和路径连起来,就构造了network. 剩下的就是跑一遍maxflow就好了。
/*
ID: thestor1
LANG: C++
TASK: stall4
*/
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <climits>
#include <cassert>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
int find_path(vector<vector<int> > &capacity, vector<vector<int> > adjs, const int sink)
{
int M = capacity.size();
std::vector<bool> visited(M, false);
// from[x] is the previous vertex visited in the shortest path from the source to x
std::vector<int> from(M, -1);
queue<int> Q;
Q.push(0);
visited[0] = true;
int where = -1, next = -1, prev = -1;
bool found = false;
while (!Q.empty())
{
where = Q.front();
Q.pop();
for (int i = 0; i < adjs[where].size(); ++i)
{
next = adjs[where][i];
if (!visited[next] && capacity[where][next] > 0)
{
Q.push(next);
visited[next] = true;
from[next] = where;
if (next == sink)
{
found = true;
break;
}
}
}
if (found)
{
break;
}
}
// we compute the path capacity
where = sink;
int path_cap = -1;
while (from[where] > -1)
{
prev = from[where];
if (path_cap > -1)
{
path_cap = min(path_cap, capacity[prev][where]);
}
else
{
path_cap = capacity[prev][where];
}
where = prev;
}
// we update the residual network; if no path is found the while loop will not be entered
where = sink;
while (from[where] > -1)
{
prev = from[where];
capacity[prev][where] -= path_cap;
capacity[where][prev] += path_cap;
where = prev;
}
// if no path is found, path_cap is infinity
if (path_cap == -1)
{
return 0;
}
return path_cap;
}
int main()
{
FILE *fin = fopen("stall4.in", "r");
FILE *fout = fopen("stall4.out", "w");
int N, M;
fscanf(fin, "%d", &N);
fscanf(fin, "%d", &M);
vector<vector<int> > capacity(N + M + 2, vector<int>(N + M + 2, 0));
vector<vector<int> > adjs(N + M + 2, vector<int>());
for (int i = 0; i < N; ++i)
{
int k;
fscanf(fin, "%d", &k);
for (int j = 0; j < k; ++j)
{
int p;
fscanf(fin, "%d", &p);
capacity[i + 1][N + p] = 1;
adjs[i + 1].push_back(N + p);
adjs[N + p].push_back(i + 1);
}
}
for (int i = 1; i <= N; ++i)
{
capacity[0][i] = 1;
adjs[0].push_back(i);
adjs[i].push_back(0);
}
for (int i = N + 1; i <= N + M; ++i)
{
capacity[i][N + M + 1] = 1;
adjs[i].push_back(N + M + 1);
adjs[N + M + 1].push_back(i);
}
int maxflow = 0;
while (true)
{
int path_cap = find_path(capacity, adjs, N + M + 1);
if (path_cap == 0)
{
break;
}
else
{
maxflow += path_cap;
}
}
// cout<<"[debug]maxflow: "<<maxflow<<endl;
fprintf(fout, "%d\n", maxflow);
fclose(fin);
fclose(fout);
return 0;
}