#include<bits/stdc++.h>
#define f first
#define s second
using namespace std;
typedef long long ll;
const int N=300005;
typedef pair<int,int> P;
int n,tot,t,V;
map<string,int> mp;
map<vector<int>,int> mp2;
vector<int> G[N];
int match[N];
bool used[N];
void add_edge(int u,int v)
{
G[u].push_back(v);
G[v].push_back(u);
}
int get_id(string str)
{
if(mp.find(str)==mp.end())
mp[str]=++tot;
return mp[str];
}
int get_ver_id(vector<int> &v)
{
if(mp2.find(v)==mp2.end())
mp2[v]=++t;
return mp2[v];
}
vector<int> v;
string str;
bool dfs(int v)
{
used[v]=true;
for(int i=0; i<G[v].size(); i++)
{
int u=G[v][i],w=match[u];
if(w<0||!used[w]&&dfs(w))
{
match[v]=u;
match[u]=v;
return true;
}
}
return false;
}
int matching()
{
int res=0;
memset(match,-1,sizeof(match));
for(int v=1; v<=V; v++)
{
if(match[v]<0)
{
memset(used,0,sizeof(used));
if(dfs(v))
res++;
}
}
return res;
}
int main()
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
int x;
scanf("%d",&x);
v.clear();
for(int j=0; j<x; j++)
{
cin>>str;
v.push_back(get_id(str));
}
//排序
sort(v.begin(),v.end());
for(int mask=1; mask<(1<<x); mask++)
{
vector<int> tmp;
for(int j=0; j<x; j++)
if(mask&(1<<j))
tmp.push_back(v[j]);
get_ver_id(tmp);
}
}
//老师对于每个算法的教的情况
//mp2存每个学生学的算法的状态
int SZ=(int)mp2.size();
for(auto p:mp2)
{
//当前这个学生学的算法
auto x=p.f;
//学的算法的数量
int sz=(int)x.size();
//学的所有算法的 状态的 编号
int id=get_ver_id(x);
//去掉其中一个学过的算法,那么就可以合作了
for(int j=0; j<sz; j++)
{
vector<int> tmp=x;
//去掉其中一个
tmp.erase(tmp.begin()+j);
if(!tmp.size())
continue;
//建边,也就是这两个点不能合作,因为状态是包含的关系
//拆点建图
add_edge(id,SZ+get_ver_id(tmp));
}
}
//要求的是 用最多的不同的路径覆盖所有点
//总的
V=2*SZ;
printf("%d\n",SZ-matching());
return 0;
}
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12686496.html
时间: 2024-10-31 12:43:03