*可以通过旁边的目录查看(´・ω・`),或者Ctrl + F
裸的最大流
P2740 [USACO4.2]草地排水Drainage Ditches
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 440+10;
const int maxm = 1100+10;
const int inf = 0x7f7f7f7f;
typedef struct Dinic{
typedef struct Edge
{
int u,v,w,nxt;
}Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1, sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
// 01 23 45
//i i^1
}
//BFS
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.emplace(S);dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
return 1;
q.emplace(v);
}
}
}
return dep[T] != inf;
}
//DFS
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i = e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w = e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0) continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll*d;
}
}
return res;
}
} Dinic;
int n,m,s,t;
int main(int argc, char const *argv[])
{
//ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
while(scanf("%d%d",&m,&n)!=EOF)
{
Dinic din; din.init();
din.S = 1,din.T = n,din.N = n+10;
int u,v,w;
rep(i,0,m)
{
scanf("%d%d%d",&u,&v,&w);
din.adde(u,v,w);
}
printf("%lld\n",din.dinic());
}
return 0;
}
P1343 地震逃生
注意判断最大流是否为0
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 440+10;
const int maxm = 4400+10;
const int inf = 0x7f7f7f7f;
typedef struct Dinic{
typedef struct Edge
{
int u,v,w,nxt;
}Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1, sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
// 01 23 45
//i i^1
}
//BFS
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.emplace(S);dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
return 1;
q.emplace(v);
}
}
}
return dep[T] != inf;
}
//DFS
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i = e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w = e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0) continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll*d;
}
}
return res;
}
} Dinic;
int n,m,x,s,t;
int main(int argc, char const *argv[])
{
//ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
while(scanf("%d%d%d",&n,&m,&x)!=EOF)
{
Dinic din; din.init();
din.S = 1,din.T = n,din.N = n+1;
int u,v,w;
rep(i,0,m)
{
scanf("%d%d%d",&u,&v,&w);
din.adde(u,v,w);
}
ll sum = din.dinic();
if(sum == 0)
{
printf("Orz Ni Jinan Saint Cow!\n");
}
else
{
ll ans = x / sum;
if(x % sum)
{
ans++;
}
printf("%lld %lld\n",sum,ans);
}
}
return 0;
}
二分图匹配
有A,B两部分
建一个超级源点S和一个超级汇点T,S连A,B连T,跑最大流就行
P2756 飞行员配对方案问题
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 440+10;
const int maxm = 4400+10;
const int inf = 0x7f7f7f7f;
typedef struct Dinic{
typedef struct Edge
{
int u,v,w,nxt;
}Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
int pre[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1, sizeof head);
memset(pre,0,sizeof pre);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
// 01 23 45
//i i^1
}
//BFS
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.emplace(S);dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
return 1;
q.emplace(v);
}
}
}
return dep[T] != inf;
}
//DFS
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i = e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w = e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0) continue;
e[i].w -= cw;
e[i^1].w += cw;
pre[v] = s;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll*d;
}
}
return res;
}
} Dinic;
int n,m,x,s,t;
int main(int argc, char const *argv[])
{
//ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
while(scanf("%d%d",&m,&n)!=EOF)
{
Dinic din; din.init();
din.S = 0,din.T = n+1 , din.N = n*2;
rep(i,1,m+1)
{
din.adde(0,i,1);
}
rep(i,m+1,n+1)
{
din.adde(i,n+1,1);
}
int u,v;
while(scanf("%d%d",&u,&v)!=EOF)
{
if(u == -1 && v == -1)
{
break;
}
din.adde(u,v,1);
}
ll res = din.dinic();
if(res == 0)
printf("No Solution!\n");
else
{
printf("%lld\n",res);
rep(i,m+1,n+1)
{
if(!din.pre[i])
{
continue;
}
printf("%d %d\n",i,din.pre[i]);
}
}
}
return 0;
}
最小割
二者取一模型
有 n 个物品和两个集合 A,B,如果将一个物品放入 A 集合会得到
a
i
a_i
ai,放入 B 集合会得到
b
i
b_i
bi。还有若干个约束集。每个物品必须且只能属于一个集合,求最大的收益(或者最小花费)。
根据约束集的不同,有2种方法。
- 两者不在同一集合会花费 w w w。两个点连双向边,边权为 w w w
- 多者同在集合A会得到收益 x x x,同在集合B会得到收益 y y y。这个时候需要建虚点,这个时候可以建一个虚点,从S向虚点连边(权为 w i w_i wi),从虚点向涉及到的物品连边(权为 i n f inf inf(无穷大)),权为 i n f inf inf的原因是不能切断虚点与物品的连接。
P2057 [SHOI2007]善意的投票
思路见第一种
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 1e4+100;
const int maxm = 4e5+100;
const int inf = 0x7f7f7f7f;
typedef struct Dinic
{
typedef struct Edge
{
int u,v,w,nxt;
} Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1,sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
}
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.push(S); dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
{
return 1;
}
q.emplace(v);
}
}
}
return dep[T] != inf;
}
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i=e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w=e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0)
continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll * d;
}
}
return res;
}
} Dinic;
int n,m,s,t;
int main(int argc, char const *argv[])
{
while(scanf("%d%d",&n,&m)!=EOF)
{
Dinic din;din.init();
s = 0,t = n+1;
din.S = 0,din.T = n+1,din.N = n+2;
int x,y;
rep(i,1,n+1)
{
scanf("%d",&x);
if(x)
{
din.adde(i,t,1);
}
else
{
din.adde(s,i,1);
}
}
rep(i,0,m)
{
scanf("%d%d",&x,&y);
din.adde(x,y,1);
din.adde(y,x,1);
}
printf("%lld\n",din.dinic() );
}
return 0;
}
P1361 小M的作物
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 1e5+10;
const int maxm = 1e7+10;
const int inf = 0x7f7f7f7f;
typedef struct Dinic{
typedef struct Edge
{
int u,v,w,nxt;
}Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1, sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
// 01 23 45
//i i^1
}
//BFS
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.emplace(S);dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
return 1;
q.emplace(v);
}
}
}
return dep[T] != inf;
}
//DFS
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i = e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w = e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0) continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll*d;
}
}
return res;
}
} Dinic;
int n,m,s,t;
int x;
int main(int argc, char const *argv[])
{
ll sum = 0;
scanf("%d",&n);
Dinic din;
din.init();
s = 0, t = n + 1;
din.S = 0,din.T = n + 1;
rep(i,1,n+1) scanf("%d",&x),sum += 1ll * x,din.adde(s,i,x);
rep(i,1,n+1) scanf("%d",&x),sum += 1ll * x,din.adde(i,t,x);
scanf("%d",&m);
din.N = (n + m * 2) * 2;
rep(i,1,m+1)
{
int k,c1,c2;
scanf("%d%d%d",&k,&c1,&c2);
sum += c1 + c2;
din.adde(s,n+i+1,c1);
din.adde(n+m+1+i,t,c2);
while(k--)
{
int s;
scanf("%d",&s);
din.adde(n+i+1,s,inf);
din.adde(s,i+n+m+1,inf);
}
}
ll res = din.dinic();
//cout << res << endl;
printf("%lld\n",sum-res);
return 0;
}
拆点
在最小割里面拆点的原因是一般是需要割点,但在网络流里面我们只能进行割边的操作。一般操作是将点i拆为i和i+n,连接两点的边权为1或者题目中的条件,当边权为0时表示这个点被割掉了,当边权为inf时表示点不能被割。
P1345 [USACO5.4]奶牛的电信Telecowmunication
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 200+100;
const int maxm = 1e4+100;
const int inf = 0x7f7f7f7f;
typedef struct Dinic
{
typedef struct Edge
{
int u,v,w,nxt;
} Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1,sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
}
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.push(S); dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
{
return 1;
}
q.emplace(v);
}
}
}
return dep[T] != inf;
}
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i=e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w=e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0)
continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll * d;
}
}
return res;
}
} Dinic;
int n,m,s,t;
int main(int argc, char const *argv[])
{
while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF)
{
Dinic din;
din.init();
din.S = s+n,din.T = t;
din.N = 2*n+3;
int x,y;
rep(i,1,n+1)
{
din.adde(i,i+n,1);
}
rep(i,0,m)
{
scanf("%d%d",&x,&y);
din.adde(x+n,y,inf);
din.adde(y+n,x,inf);
}
printf("%lld\n",din.dinic());
}
return 0;
}
P2944 [USACO09MAR]地震损失2Earthquake Damage 2
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 1e4+100;
const int maxm = 1e5+100;
const int inf = 0x7f7f7f7f;
typedef struct Dinic
{
typedef struct Edge
{
int u,v,w,nxt;
} Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1,sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
}
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.push(S); dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
{
return 1;
}
q.emplace(v);
}
}
}
return dep[T] != inf;
}
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i=e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w=e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0)
continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll * d;
}
}
return res;
}
} Dinic;
int n,m,s;
int vis[maxn];
int main(int argc, char const *argv[])
{
while(scanf("%d%d%d",&n,&m,&s)!=EOF)
{
memset(vis,0,sizeof vis);
Dinic din; din.init();
din.S = 0,din.T = 1,din.N = 2*n+10;
int x,y;
rep(i,0,m)
{
scanf("%d%d",&x,&y);
din.adde(x+n,y,inf);
din.adde(y+n,x,inf);
}
rep(i,0,s)
{
scanf("%d",&x);
vis[x] = 1;
din.adde(x,x+n,inf);
din.adde(0,x,inf);
}
rep(i,1,n+1)
{
//din.adde(i+n,2*n+1,inf);
if(vis[i] == 0)
din.adde(i,i+n,1);
}
printf("%lld\n",din.dinic());
}
return 0;
}
P4662 [BalticOI 2008]黑手党
需要输出方案,在残余网络中dfs
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 400+100;
const int maxm = 1e5+100;
const int inf = 0x7f7f7f7f;
int vis[maxn];
typedef struct Dinic
{
typedef struct Edge
{
int u,v,w,nxt;
} Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1,sizeof head);
hcnt = 2;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
}
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.push(S); dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
{
return 1;
}
q.emplace(v);
}
}
}
return dep[T] != inf;
}
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i=e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w=e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0)
continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll * d;
}
}
return res;
}
void dfs1(int u)
{
vis[u] = 1;
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v;
if(e[i].w && !vis[v])
dfs1(v);
}
}
void solve()
{
VI ans;
for(int i = 2;i<=hcnt;i+=2)
{
int u = e[i^1].v,v = e[i].v;
if(vis[u] && !vis[v])
ans.pb(u);
}
//cout << ans.size() << endl;
rep(i,0,ans.size())
{
if(i == 0)
printf("%d",ans[i]);
else
{
printf(" %d",ans[i]);
}
}
printf("\n");
}
} Dinic;
int n,m,s,t;
int main(int argc, char const *argv[])
{
while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF)
{
Dinic din;din.init();
memset(vis,0,sizeof vis);
int w;
rep(i,1,n+1)
{
scanf("%d",&w);
din.adde(i,i+n,w);
}
int x,y;
rep(i,1,m+1)
{
scanf("%d%d",&x,&y);
din.adde(x+n,y,inf);
din.adde(y+n,x,inf);
}
din.S = s,din.T = t+n;
din.N = 2*n+3;
din.dinic();
//cout << din.dinic() << endl;
din.dfs1(s);
din.solve();
}
return 0;
}
另一类拆点
一种模型就是有3个集合A,B,C,A和B有关系,B和C有关系,建图A连B,B连C,但是因为B里的元素只能被选一次,这个时候需要把B里的每个元素拆成2个点,边权为1,表示只能被选一次
P1231 教辅的组成
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 4e4+100;
const int maxm = 1e6+100;
const int inf = 0x7f7f7f7f;
typedef struct Dinic
{
typedef struct Edge
{
int u,v,w,nxt;
} Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1,sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
}
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.push(S); dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
{
return 1;
}
q.emplace(v);
}
}
}
return dep[T] != inf;
}
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i=e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w=e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0)
continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll * d;
}
}
return res;
}
} Dinic;
int n1,n2,n3;
int m;
int main(int argc, char const *argv[])
{
Dinic din;din.init();
scanf("%d%d%d",&n1,&n2,&n3);
int x,y;
rep(i,1,n1+1)
{
din.adde(i,i+n1,1);
}
rep(i,1,n2+1)
{
din.adde(0,i+2*n1,1);
}
rep(i,1,n3+1)
{
din.adde(i+2*n1+n2,2*n1+n2+n3+1,1);
}
scanf("%d",&m);
rep(i,0,m)
{
scanf("%d%d",&x,&y);
din.adde(y+2*n1,x,inf);
}
scanf("%d",&m);
rep(i,0,m)
{
scanf("%d%d",&x,&y);
din.adde(x+n1,y+2*n1+n2,inf);
}
din.S = 0;din.T = 2*n1+n2+n3+1;
din.N = 2*n1+n2+n3+1+10;
ll ans = din.dinic();
cout << ans << endl;
return 0;
}
P1402 酒店之王
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 4e3+100;
const int maxm = 1e5+100;
const int inf = 0x7f7f7f7f;
typedef struct Dinic
{
typedef struct Edge
{
int u,v,w,nxt;
} Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1,sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
}
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.push(S); dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
{
return 1;
}
q.emplace(v);
}
}
}
return dep[T] != inf;
}
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i=e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w=e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0)
continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll * d;
}
}
return res;
}
} Dinic;
int n1,n2,n3;
int m;
int main(int argc, char const *argv[])
{
Dinic din;din.init();
scanf("%d%d%d",&n1,&n2,&n3);
int x,y;
rep(i,1,n1+1)
{
din.adde(i,i+n1,1);
}
rep(i,1,n2+1)
{
din.adde(0,i+2*n1,1);
}
rep(i,1,n3+1)
{
din.adde(i+2*n1+n2,2*n1+n2+n3+1,1);
}
rep(i,1,n1+1)
{
rep(y,1,n2+1)
{
scanf("%d",&x);
if(x == 1)
din.adde(y+2*n1,i,inf);
}
}
rep(i,1,n1+1)
{
rep(y,1,n3+1)
{
scanf("%d",&x);
if(x == 1)
din.adde(i+n1,2*n1+n2+y,inf);
}
}
din.S = 0;din.T = 2*n1+n2+n3+1;
din.N = 2*n1+n2+n3+1+10;
ll ans = din.dinic();
cout << ans << endl;
return 0;
}
P2891 [USACO07OPEN]吃饭Dining
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 4e3+100;
const int maxm = 1e5+100;
const int inf = 0x7f7f7f7f;
typedef struct Dinic
{
typedef struct Edge
{
int u,v,w,nxt;
} Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1,sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
}
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.push(S); dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
{
return 1;
}
q.emplace(v);
}
}
}
return dep[T] != inf;
}
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i=e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w=e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0)
continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll * d;
}
}
return res;
}
} Dinic;
int n1,n2,n3;
int m;
int main(int argc, char const *argv[])
{
while(scanf("%d%d%d",&n1,&n2,&n3)!=EOF)
{
Dinic din;din.init();
int x,y;
rep(i,1,n1+1)
{
din.adde(i,i+n1,1);
}
rep(i,1,n2+1)
{
din.adde(0,i+2*n1,1);
}
rep(i,1,n3+1)
{
din.adde(i+2*n1+n2,2*n1+n2+n3+1,1);
}
int a;
rep(i,1,n1+1)
{
scanf("%d%d",&x,&y);
rep(j,1,x+1)
{
scanf("%d",&a);
din.adde(a+2*n1,i,inf);
}
rep(j,1,y+1)
{
scanf("%d",&a);
din.adde(i+n1,2*n1+n2+a,inf);
}
}
din.S = 0;din.T = 2*n1+n2+n3+1;
din.N = 2*n1+n2+n3+1+10;
ll ans = din.dinic();
printf("%lld\n",ans);
}
return 0;
}