最大流

套题链接:https://vjudge.net/contest/126475#overview
A题-基础模板题


#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<queue>
#define maxn 210
#define INF 0xfffffff
using namespace std;

int flow[maxn][maxn];//邻接矩阵存放图
int mark[maxn], pre[maxn];//mark标记是否访问过,pre记录增广路
int m, n, f;//f为最大流

void max_flow()
{
    //不断寻找增广路,直到找不到为止,找不到标记为mark[n]=0
    while (1)
    {
        memset(mark, 0, sizeof(mark));
        memset(pre, 0, sizeof(pre));

        queue<int>Q;
        mark[1] = 1;
        Q.push(1);
        while (!Q.empty())
        {
            int cnt = Q.front();
            Q.pop();
            //出口:找到增广路,退出
            if (cnt == n) {
                break;
            }
            for (int i = 1; i <= n; i++) {
                if (!mark[i] && flow[cnt][i] > 0) {//没遍历过且有通路
                    mark[i] = 1;
                    Q.push(i);
                    pre[i] = cnt;
                }
            }
        }
        //没找到增广路,直接跳出
        if (!mark[n])
            break;
        //计算该增广路最大可增加的流量
        int minx = INF;
        for (int i = n; i != 1; i = pre[i]) {
            minx = min(flow[pre[i]][i], minx);
        }
        for (int i = n; i != 1; i = pre[i]) {
            flow[pre[i]][i] -= minx;//更新正向流量
            flow[i][pre[i]] += minx;//更新反向流量
        }
        f += minx;//???
    }
}

int main()
{
    while (~scanf("%d %d",&m,&n))
    {
        memset(flow, 0, sizeof(flow));
        for (int i = 0; i < m; i++) {
            int u, v, len;
            scanf("%d %d %d", &u, &v, &len);
            flow[u][v] += len;//有重边,要加上
        }
        f = 0;
        max_flow();
        printf("%d\n", f);
    }
    return 0;
}

B题-改改模板

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<queue>
#define maxn 210
#define INF 0xfffffff
using namespace std;

int flow[maxn][maxn];//邻接矩阵存放图
int mark[maxn], pre[maxn];//mark标记是否访问过,pre记录增广路
int m, n, f;//f为最大流
//模板
void max_flow()
{
    //不断寻找增广路,直到找不到为止,找不到标记为mark[n]=0
    while (1)
    {
        memset(mark, 0, sizeof(mark));
        memset(pre, 0, sizeof(pre));

        queue<int>Q;
        mark[1] = 1;
        Q.push(1);
        while (!Q.empty())
        {
            int cnt = Q.front();
            Q.pop();
            //出口:找到增广路,退出
            if (cnt == n) {
                break;
            }
            for (int i = 1; i <= n; i++) {
                if (!mark[i] && flow[cnt][i] > 0) {//没遍历过且有通路
                    mark[i] = 1;
                    Q.push(i);
                    pre[i] = cnt;
                }
            }
        }
        //没找到增广路,直接跳出
        if (!mark[n])
            break;
        //计算该增广路最大可增加的流量
        int minx = INF;
        for (int i = n; i != 1; i = pre[i]) {
            minx = min(flow[pre[i]][i], minx);
        }
        for (int i = n; i != 1; i = pre[i]) {
            flow[pre[i]][i] -= minx;//更新正向流量
            flow[i][pre[i]] += minx;//更新反向流量
        }
        f += minx;//把遍历过的路径加起来
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    int t = 1;
    while (T--)
    {
        memset(flow, 0, sizeof(flow));
        scanf("%d%d", &n, &m);
        for (int i = 0; i < m; i++) {
            int u, v, len;
            scanf("%d %d %d", &u, &v, &len);
            flow[u][v] += len;//有重边,要加上
        }
        f = 0;
        max_flow();
        printf("Case %d: %d\n", t, f);
        t++;
    }
    return 0;
}

C题


#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<queue>
#define maxn 1010
#define INF 0xfffffff
using namespace std;
int full_flow;
struct Edge
{
    int from, to, cap, flow;
    Edge(){}
    Edge(int f,int t,int c,int f1):from(f),to(t),cap(c),flow(f1){}
};
struct Dinic
{
    int n, m, s, t;
    vector<Edge> edges;
    vector<int>G[maxn];
    bool vis[maxn];
    int cur[maxn];
    int d[maxn];

    void init(int n, int s, int t)
    {
        this->n = n, this->s = s, this->t = t;
        edges.clear();
        for (int i = 0; i < n; i++)
            G[i].clear();
    }
    void AddEdge(int from, int to, int cap)
    {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }
    bool bfs()
    {
        queue<int>Q;
        memset(vis, 0, sizeof(vis));
        vis[s] = true;
        d[s] = 0;
        Q.push(s);
        while (!Q.empty())
        {
            int x = Q.front();
            Q.pop();
            for (int i = 0; i < G[x].size(); i++) {
                Edge& e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = true;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int dfs(int x, int a)
    {
        if (x == t || a == 0)
            return a;
        int flow = 0, f;
        for (int &i = cur[x]; i < G[x].size(); i++) {
            Edge &e = edges[G[x][i]];
            if (d[e.to] == d[x] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow)))>0) {
                e.flow += f;
                edges[G[x][i] ^ 1].flow -= f;//
                flow += f;
                a -= f;
                if (a == 0) break;
            }
        }
        return flow;
    }

    int max_flow()
    {
        int ans = 0;
        while (bfs())
        {
            memset(cur, 0, sizeof(cur));
            ans += dfs(s, INF);
        }
        return ans;
    }
}DC;
int main()
{
    int T;
    scanf("%d", &T);
    for (int kase = 1; kase <= T; kase++) {
        int n, m;
        scanf("%d%d", &n, &m);
        full_flow = 0;
        int src = 0, dst = 500 + n + 1;
        DC.init(500 + 2 + n, src, dst);
        bool vis[maxn];//表示第i天是否被用到
        memset(vis, 0, sizeof(vis));

        for (int i = 1; i <= n; i++) {
            int P, S, E;
            scanf("%d%d%d", &P, &S, &E);
            DC.AddEdge(src, 500 + i, P);
            full_flow += P;
            for (int j = S; j <= E; j++) {
                DC.AddEdge(500 + i, j, 1);
                vis[j] = true;
            }
        }

        for (int i = 1; i <= 500; i++)
            if (vis[i])
                DC.AddEdge(i, dst, m);
        printf("Case %d: %s\n\n", kase, DC.max_flow() == full_flow ? "Yes" : "No");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值