题目链接
题目大意:
解题思路:
- 首先我们发现对于每条边至少要覆盖一次,最多覆盖无数次
- 那么就有点像上下界网络流了
[
1
,
I
N
F
]
[1,INF]
[1,INF]的限制关系
- 跑一边最小流就可以了!!
#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = N;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {
read(first);
read(args...);
}
struct node {
int to, next, len;
}e[maxn];
int head[maxn], cnt;
int n, m, s, t;
inline void add(int from, int to, int len) {
e[cnt] = {to,head[from],len};
head[from] = cnt ++;
e[cnt] = {from,head[to],0};
head[to] = cnt ++;
}
int d[maxn],cur[maxn];
int pre[maxn], flow[maxn];
bool bfs() {
ms(d,0);
queue<int> q;
q.push(s); d[s] = 1;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].to;
if(d[v] || e[i].len <= 0) continue;
q.push(v);
d[v] = d[u] + 1;
}
}
for(int i = 0; i <= t; ++ i) cur[i] = head[i];
return d[t] != 0;
}
int dfs(int u, int flow) {
if(u == t) return flow;
for(int &i = cur[u]; ~i; i = e[i].next) {
int v = e[i].to;
if(d[u] + 1 != d[v] || e[i].len <= 0) continue;
int delta = dfs(v,min(flow,e[i].len));
if(delta <= 0) continue;
e[i].len -= delta;
e[i^1].len += delta;
return delta;
}
return 0;
}
int get_maxflow() {
int maxFlow = 0, delta;
while(bfs())
while(delta = dfs(s,INF))
maxFlow += delta;
return maxFlow;
}
int Tn, Tm, Gx[maxn], in[maxn], out[maxn];
void init() {
ms(in,0), ms(out,0), ms(head,-1);
cnt = 0;
}
int main() {
IOS;
init();
cin >> n;
int s1 = 0, t1 = n+1, s2 = n+2, t2 = n+3;
for(int i = 1; i <= n; ++ i) {
int x;
cin >> x;
for(int j = 1; j <= x; ++ j) {
int id;
cin >> id;
in[id] ++;
out[i] ++;
add(i,id,INF-1);
}
add(s1,i,INF-1);
add(i,t1,INF-1);
}
for(int i = 0; i <= n+1; ++ i)
if(in[i] > out[i]) add(s2,i,in[i]-out[i]);
else add(i,t2,out[i]-in[i]);
add(t1,s1,INF);
s = s2, t = t2;
get_maxflow();
int flow1 = e[cnt-1].len;
e[cnt-1].len=0;
e[cnt-2].len=0;
s = t1, t = s1;
cout << flow1 - get_maxflow();
return 0;
}