题解 社会黄油飞
看怎么处理这个式子
赛时思路是枚举点集大小然后二分网络流check
于是就不会了
其实不用枚举点集大小,直接移项,有
\[e(s)-lim|s|>-lim
\]
其中 \(e(s)\) 为 s 的导出子图大小
发现选了一条边就必须选对应的两个端点,跑最大权闭合子图即可
但是直接跑的话会把 \(s=\varnothing\) 算进去,这样是不合法的
所以要枚举并钦定选一个点
这样的话要跑 \(n\) 次网络流,复杂度就假了
发现每次删除的边只有一条,考虑退流
对于一条边 \((u, v)\),从 \(t\) 向 \(v\) 跑最大流,从 \(u\) 向 \(s\) 跑最大流
再将这条边的流量清空即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define fir first
#define sec second
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m, lim;
pair<int, int> g[N];
int head[N], dep[N], cur[N], id[N], ecnt=1, s, t, ans=0;
struct edge{int to, next, val;}e[N<<1];
inline void add(int s, int t, int w) {e[++ecnt]={t, head[s], w}; head[s]=ecnt;}
bool bfs() {
memset(dep, 0, sizeof(dep));
queue<int> q;
cur[s]=head[s]; dep[s]=1;
q.push(s);
int u;
while (q.size()) {
u=q.front(); q.pop();
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (e[i].val && !dep[v]) {
dep[v]=dep[u]+1;
cur[v]=head[v];
if (v==t) return 1;
q.push(v);
}
}
}
return 0;
}
int dfs(int u, int in) {
if (u==t||!in) return in;
int rest=in, tem;
for (int i=cur[u],v; ~i; cur[u]=i=e[i].next) {
v = e[i].to;
if (e[i].val && dep[v]==dep[u]+1) {
tem=dfs(v, min(e[i].val, rest));
if (!tem) dep[v]=0;
e[i].val-=tem;
e[i^1].val+=tem;
rest-=tem;
if (!rest) break;
}
}
return in-rest;
}
int dinic() {
while (bfs()) ans+=dfs(s, INF);
return ans;
}
int pushback(int u, int in) {
//cout<<"pushback: "<<u<<' '<<in<<endl;
if (u==s||!in) return in;
int rest=in, tem;
for (int i=head[u],v; ~i; i=e[i].next) if (i&1 && e[i].val) {
v = e[i].to;
//cout<<"v: "<<v<<endl;
tem=pushback(v, min(rest, e[i].val));
e[i].val-=tem;
e[i^1].val+=tem;
rest-=tem;
if (!rest) break;
}
return in-rest;
}
signed main()
{
freopen("socialbutterfly.in", "r", stdin);
freopen("socialbutterfly.out", "w", stdout);
n=read(); m=read(); lim=read(); s=n+m+1; t=n+m+2;
memset(head, -1, sizeof(head));
for (int i=1; i<=m; ++i) g[i].fir=read(), g[i].sec=read();
for (int i=1; i<=m; ++i) {
add(s, i, 1), add(i, s, 0);
add(i, g[i].fir+m, INF), add(g[i].fir+m, i, 0);
add(i, g[i].sec+m, INF), add(g[i].sec+m, i, 0);
}
for (int i=1; i<=n; ++i) id[i]=ecnt+1, add(i+m, t, lim), add(t, i+m, 0);
for (int i=1; i<=n; ++i) {
//cout<<"i: "<<i<<endl;
ans-=e[id[i]^1].val;
pushback(i+m, e[id[i]^1].val);
e[id[i]].val=0; e[id[i]^1].val=0;
int t=dinic();
//cout<<"t: "<<t<<endl;
if (m-t>0) {puts("Yes"); return 0;}
e[id[i]].val=lim;
}
puts("No");
return 0;
}