最大流训练与总结

8 篇文章 0 订阅
7 篇文章 0 订阅

*可以通过旁边的目录查看(´・ω・`),或者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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值