网络流小结 专题题解汇总

  • hdu 3572 Task Schedule 任务题
    拆点(天)
    题意:
    现在你有m个机器,n个任务,每个任务有三个属性p,s,e,表示只能在[p,e]区间内花s的时间做完这个任务,一个机器一个时间只能做一个任务,一个任务一个时间只能被一个机器做,现在问你能不能完成全部的任务。
    n,m <= 500
    1 <= p,s,e <= 500
    思路:
    设0是源点,1~500是机器,501~1000是天数,1100是汇点,假设任务i三个属性p,s,e,源点连一条容量s的边到点 i,然后点 i 分别向每个[500+p, 500+e]的顶点连容量为1的边,最后501~1000向汇点连一条容量为1的边,跑个最大流,如果最大流等于所有任务s之和就是YES,否则就是NO。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3000;   //点数
const int INF = 0x3f3f3f3f;
int tc,n,m;
struct Edge{
    int from, to, cap, flow;  //如果要开ll的话,这边也要开ll
    Edge(int u, int v, int c, int f)
        : from(u), to(v), cap(c), flow(f) {}
};
struct Dicnic {
    #define Type int
    int n, m, s, t;        //节点数,边数(包括反向弧),源点编号和汇点编号
    vector<Edge> edges;    //边表。edge[e]和edge[e^1]互为反向弧
    vector<int> G[maxn];   //邻接表,G[i][j]表示节点i的第j条边在e数组中的编号
    bool vis[maxn];        //BFS使用
    Type d[maxn];           //从起点到i的距离
    int cur[maxn];         //当前弧下标
    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; ++i) G[i].clear();
        edges.clear();
    }
    void addEdge(int from, int to, int cap) {
        edges.emplace_back(Edge(from, to, cap, 0));
        edges.emplace_back(Edge(to, from, 0, 0));
        m = int(edges.size());
        G[from].emplace_back(m-2);
        G[to].emplace_back(m-1);
    }
    bool BFS() {
        memset(vis, 0, sizeof(vis));
        memset(d, 0, sizeof(d));
        queue<int> q;
		while (!q.empty()) q.pop();
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = 0; i < int(G[x].size()); ++i) {
                Edge &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    Type DFS(int x, Type a) {
        if (x == t || a == 0) return a;
        Type flow = 0, f;
        for (int &i = cur[x]; i < int(G[x].size()); ++i) { //从上次考虑的弧
            Edge &e = edges[G[x][i]];
            if (d[x]+1 == d[e.to] && (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;
    }
    Type Maxflow(int s, int t) {
        this->s = s; this->t = t;
        Type flow = 0;
        while (BFS()) {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, INF);
        }
        return flow;
    }
    #undef Type
}dicnic;
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    cin>>tc;
    int kase=1;
    while(tc--){
        int sum=0;
        cin>>n>>m;
        dicnic.init(1300);
        for(int i=1; i<=n; ++i){
            int p,s,e;
            cin>>p>>s>>e;
            sum+=s;
            dicnic.addEdge(0,i,s);
            for(int j=500+p; j<=500+e; ++j) dicnic.addEdge(i,j,1);
        }
        for(int i=501; i<=1000; ++i) dicnic.addEdge(i,1100,m);
        int all=dicnic.Maxflow(0,1100);
        cout<<"Case "<<kase++<<": ";
        if(all==sum) cout<<"Yes"<<'\n';
        else cout<<"No"<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

  • hdu 2732 Leapin’ Lizards 蜥蜴题
  • 拆点(柱子)
    题意:
    给你一张图,上面有柱子和蜥蜴,有蜥蜴的地方一定有柱子,每根柱子还有耐久度,每个蜥蜴最多能跳到离原来位置<=d距离的柱子,这个距离是x的距离差+y的距离差。
    思路:
    因为柱子有耐久度,所以可拆点连一条有容量的边来表示他的限制。
    设源点为s,入点为t。
    如果p有蜥蜴,那么s到p连一条容量1的边。
    如果p可以跳到安全地带,那么p+n*m到t连一条容量为INF的边。
    接下来就是内部柱子里面乱跳了,4个for搞一下。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1100;   //点数
const int INF = 0x3f3f3f3f; //ll 0x8个3fLL
int tc, n, m, d, pi[40][40], cnt[40][40];
string a[40],b[40];
struct Edge{
    int from, to, cap, flow;  //如果要开ll的话,这边也要开ll
    Edge(int u, int v, int c, int f)
        : from(u), to(v), cap(c), flow(f) {}
};
struct Dicnic {
    #define Type int
    int n, m, s, t;        //节点数,边数(包括反向弧),源点编号和汇点编号
    vector<Edge> edges;    //边表。edge[e]和edge[e^1]互为反向弧
    vector<int> G[maxn];   //邻接表,G[i][j]表示节点i的第j条边在e数组中的编号
    bool vis[maxn];        //BFS使用
    Type d[maxn];           //从起点到i的距离
    int cur[maxn];         //当前弧下标
    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; ++i) G[i].clear();
        edges.clear();
    }
    void addEdge(int from, int to, int cap) {
        edges.emplace_back(Edge(from, to, cap, 0));
        edges.emplace_back(Edge(to, from, 0, 0));
        m = int(edges.size());
        G[from].emplace_back(m-2);
        G[to].emplace_back(m-1);
    }
    bool BFS() {
        memset(vis, 0, sizeof(vis));
        memset(d, 0, sizeof(d));
        queue<int> q;
		while (!q.empty()) q.pop();
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = 0; i < int(G[x].size()); ++i) {
                Edge &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    Type DFS(int x, Type a) {
        if (x == t || a == 0) return a;
        Type flow = 0, f;
        for (int &i = cur[x]; i < int(G[x].size()); ++i) { //从上次考虑的弧
            Edge &e = edges[G[x][i]];
            if (d[x]+1 == d[e.to] && (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;
    }
    Type Maxflow(int s, int t) {
        this->s = s; this->t = t;
        Type flow = 0;
        while (BFS()) {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, INF);
        }
        return flow;
    }
    #undef Type
}dicnic;
int myabs(int x) {return (x<0?-x:x);}
int getdist(int x1, int y1, int x2, int y2) {
    int d1=myabs(x1-x2), d2=myabs(y1-y2);
    return (d1+d2);
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    int kase=1;
    cin>>tc;
    while(tc--){
        dicnic.init(950);
        cin>>n>>d;
        for(int i=0; i<n; ++i) cin>>a[i];
        for(int i=0; i<n; ++i) cin>>b[i];
        m=int(a[0].size());
        int tot=0;
        memset(cnt,0,sizeof(cnt));
        memset(pi,0,sizeof(pi));
        for(int i=0; i<n; ++i){
            for(int j=0; j<m; ++j){
                int num=int(a[i][j]-'0');
                pi[i][j]=num;
                if(num!=0) {
                   cnt[i][j]=++tot;
                   dicnic.addEdge(cnt[i][j], cnt[i][j]+400, num);
                }
            }
        }
        for(int i=0; i<n; ++i){
            for(int j=0; j<m; ++j){
                if(cnt[i][j]==0) continue;
                for(int ii=0; ii<n; ++ii){
                    for(int jj=0; jj<m; ++jj){
                        if(i==ii && j==jj) continue;
                        if(cnt[ii][jj]==0) continue;
                        if(getdist(i, j, ii, jj) <= d) {
                            dicnic.addEdge(cnt[i][j]+400, cnt[ii][jj], INF);
                        }
                    }
                }
            }
        }
        int sum=0;
        for(int i=0; i<n; ++i){
            for(int j=0; j<m; ++j){
                if(b[i][j]=='L') {
                    ++sum;
                    dicnic.addEdge(0, cnt[i][j], 1);
                }
            }
        }
        for(int i=0; i<n; ++i){
            for(int j=0; j<m; ++j){
                if(cnt[i][j]==0) continue;
                int dis;
                bool ok=false;
                dis=i;
                if(d>dis) ok=true;
                dis=j;
                if(d>dis) ok=true;
                dis=n-1-i;
                if(d>dis) ok=true;
                dis=m-1-j;
                if(d>dis) ok=true;
                if(ok) {
                    dicnic.addEdge(cnt[i][j]+400, 900, INF);
                }
            }
        }
        int res=dicnic.Maxflow(0, 900);
        if(sum-res>1) cout<<"Case #"<<kase++<<": "<<sum-res<<" lizards were left behind."<<'\n';
        else if(sum-res==1) cout<<"Case #"<<kase++<<": "<<sum-res<<" lizard was left behind."<<'\n';
        else cout<<"Case #"<<kase++<<": no lizard was left behind."<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}


  • hdu 2883 kebab 烤肉题(和任务题类似)
    离散化
    题意:
    跟hdu 3572,也就是这个小结的第一题题意基本一样,就差了两点。
    1.允许的时间变成了[s,e)而不是[s,e]。
    2.s和e的范围变成了5000而不是500;
    思路:
    因为dicnic的上界复杂度是O(V^2*E)。你把5000个天全都拆出来肯定超时,因为只有200个时间段,所以可以离散化处理。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1100;   //点数
const int INF = 0x3f3f3f3f; //ll 0x8个3fLL
struct Edge{
    int from, to, cap, flow;  //如果要开ll的话,这边也要开ll
    Edge(int u, int v, int c, int f)
        : from(u), to(v), cap(c), flow(f) {}
};
struct node{
    int l,r;
    node(){}
    node(int _l, int _r):l(_l),r(_r){}
}nd[maxn];
int n,m,all[maxn],si[maxn],ni[maxn],ei[maxn],ti[maxn];
struct Dicnic {
    #define Type int
    int n, m, s, t;        //节点数,边数(包括反向弧),源点编号和汇点编号
    vector<Edge> edges;    //边表。edge[e]和edge[e^1]互为反向弧
    vector<int> G[maxn];   //邻接表,G[i][j]表示节点i的第j条边在e数组中的编号
    bool vis[maxn];        //BFS使用
    Type d[maxn];           //从起点到i的距离
    int cur[maxn];         //当前弧下标
    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; ++i) G[i].clear();
        edges.clear();
    }
    void addEdge(int from, int to, int cap) {
        edges.emplace_back(Edge(from, to, cap, 0));
        edges.emplace_back(Edge(to, from, 0, 0));
        m = int(edges.size());
        G[from].emplace_back(m-2);
        G[to].emplace_back(m-1);
    }
    bool BFS() {
        memset(vis, 0, sizeof(vis));
        memset(d, 0, sizeof(d));
        queue<int> q;
		while (!q.empty()) q.pop();
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = 0; i < int(G[x].size()); ++i) {
                Edge &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    Type DFS(int x, Type a) {
        if (x == t || a == 0) return a;
        Type flow = 0, f;
        for (int &i = cur[x]; i < int(G[x].size()); ++i) { //从上次考虑的弧
            Edge &e = edges[G[x][i]];
            if (d[x]+1 == d[e.to] && (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;
    }
    Type Maxflow(int s, int t) {
        this->s = s; this->t = t;
        Type flow = 0;
        while (BFS()) {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, INF);
        }
        return flow;
    }
    #undef Type
}dicnic;
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    while(cin>>n>>m){
        dicnic.init(1050);
        int tot=0, sum=0;
        for(int i=1; i<=n; ++i){
            cin>>si[i]>>ni[i]>>ei[i]>>ti[i];
            sum+=ni[i]*ti[i];
            dicnic.addEdge(0, i, ni[i]*ti[i]);
            all[++tot]=si[i]; all[++tot]=ei[i];
            nd[i]=node(si[i],ei[i]);
        }
        sort(all+1, all+1+tot);
        for(int i=1; i<=n; ++i){
            int ia=lower_bound(all+1, all+1+tot, nd[i].l)-all;
            int ib=lower_bound(all+1, all+1+tot, nd[i].r)-all;
            for(int j=ia; j<ib; ++j) dicnic.addEdge(i, 200+j, INF);
        }
        for(int i=1; i<tot; ++i){
            int num=all[i+1]-all[i];
            dicnic.addEdge(200+i, 1000, num*m);
        }
        int maxflow=dicnic.Maxflow(0, 1000);
        if(maxflow==sum) cout<<"Yes"<<'\n';
        else cout<<"No"<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

  • hdu 1533 回家题
    二分图最小匹配-> 二分图最大权匹配(KM+负边)或者 最小费用最大流(mcmf)
    题意:
    给你一个n*m的矩阵上面有mHm代表人,H代表房子,有相同数量的人和房子,现在问你让所有人都走到房子里的最小步数和是多少。
    思路:
    如果用mcmf做,设源点为s,汇点为t。
    源点向每个m连一条容量为1,代价为0的流。
    m向每个H连一条容量为1,代价为坐标绝对值差之和的流。
    每个H向t连一条容量为1,代价为0的流。
    然后跑mcmf,最小费用就是答案。
    ==============================================
    用km做就更简单了,直接m和H之间连负边,然后跑km。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1100;      //点数
const int INF = 0x3f3f3f3f;
int n, m, num[maxn][maxn];
char mat[maxn][maxn];
struct Edge{
    int from, to, cap, flow, cost;
    Edge(int u, int v, int c, int f, int cc)
        : from(u), to(v), cap(c), flow(f), cost(cc) {}
};
struct MCMF {
    int n, m;
    vector<Edge> edges;
    vector<int> G[maxn];
    int inq[maxn];  //是否在队列中
    int d[maxn];    //bellmanford
    int p[maxn];    //上一条弧
    int a[maxn];    //可改进量
    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; ++i) G[i].clear();
        edges.clear();
    }
    void addEdge(int from, int to, int cap, int cost) {
        edges.emplace_back(Edge(from, to, cap, 0, cost));
        edges.emplace_back(Edge(to, from, 0, 0, -cost));
        m = int(edges.size());
        G[from].emplace_back(m - 2);
        G[to].emplace_back(m - 1);
    }
    bool spfa(int s, int t, int &flow, ll &cost) {
        for (int i = 1; i <= n; ++i) d[i] = INF;
        memset(inq, 0, sizeof(inq));
        d[s] = 0;
        inq[s] = 1;
        p[s] = 0;
        a[s] = INF;
        queue<int> q;
        q.push(s);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            inq[u] = 0;
            for (int i = 0; i < int(G[u].size()); ++i) {
                Edge &e = edges[G[u][i]];
                if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
                    d[e.to] = d[u] + e.cost;
                    p[e.to] = G[u][i];
                    a[e.to] = min(a[u], e.cap - e.flow);
                    if (!inq[e.to]) {
                        q.push(e.to);
                        inq[e.to] = 1;
                    }
                }
            }
        }
		//if (d[t] > k) return false;    //如果费用大于k就退出
		//if (d[t] >= 0) return false;   //最小费用流
        if (d[t] == INF) return false;
        flow += a[t];
        cost += (ll)d[t] * (ll)a[t];
        for (int u = t; u != s; u = edges[p[u]].from) {
            edges[p[u]].flow += a[t];
            edges[p[u] ^ 1].flow -= a[t];
        }
        return true;
    }
    int MincostMaxflow(int s, int t, ll &cost) {
        int flow = 0;
        cost = 0;
        while (spfa(s, t, flow, cost));
        return flow;
    }
}mcmf;
int myabs(int x) {return (x<0?-x:x);}
int getdist(int x1, int y1, int x2, int y2){
    int ret=myabs(x1-x2)+myabs(y1-y2);
    return ret;
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    while(cin>>n>>m){
        if(!n && !m) break;
        mcmf.init(1050);
        for(int i=0; i<=n; ++i) for(int j=1; j<=m; ++j) num[i][j]=0;
        for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) cin>>mat[i][j];
        int tot=0;
        for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) if(mat[i][j]=='m') num[i][j]=++tot;
        for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) if(mat[i][j]=='H') num[i][j]=++tot;
        for(int i=1; i<=n; ++i) {
            for(int j=1; j<=m; ++j){
                if(mat[i][j]=='m') mcmf.addEdge(0, num[i][j], 1, 0);
                else if(mat[i][j]=='H') mcmf.addEdge(num[i][j], 1000, 1, 0);
            }
        }
        for(int i=1; i<=n; ++i){
            for(int j=1; j<=m; ++j){
                if(mat[i][j]=='m') {
                    for(int ii=1; ii<=n; ++ii){
                        for(int jj=1; jj<=m; ++jj){
                            if(mat[ii][jj]=='H'){
                                mcmf.addEdge(num[i][j], num[ii][jj], 1, getdist(i, j, ii, jj));
                            }
                        }
                    }
                }
            }
        }
        ll cost=0;
        ll maxflow=mcmf.MincostMaxflow(0, 1000, cost);
        cout<<cost<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

  • hdu 1565 方格取数 方格题
    最大点权独立集 = 所有的点权 - 最小点权覆盖集(最小割)
    题意:
    现在有一个n*n的矩阵,里面每个格子都有一个非负数,现在规定取出来的数不能位置不能相邻,现在问你取出来数的值的最大和是多少。
    思路:
    最大点权独立集 = 所有的点权 - 最小点权覆盖集(最小割)
    有点抽象,先记住再说。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000;   //点数
const int INF = 0x3f3f3f3f; //ll 0x8个3fLL
int n, mat[maxn][maxn], num[maxn][maxn];
struct Edge{
    int from, to, cap, flow;  //如果要开ll的话,这边也要开ll
    Edge(int u, int v, int c, int f)
        : from(u), to(v), cap(c), flow(f) {}
};
struct Dicnic {
    #define Type int
    int n, m, s, t;        //节点数,边数(包括反向弧),源点编号和汇点编号
    vector<Edge> edges;    //边表。edge[e]和edge[e^1]互为反向弧
    vector<int> G[maxn];   //邻接表,G[i][j]表示节点i的第j条边在e数组中的编号
    bool vis[maxn];        //BFS使用
    Type d[maxn];           //从起点到i的距离
    int cur[maxn];         //当前弧下标
    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; ++i) G[i].clear();
        edges.clear();
    }
    void addEdge(int from, int to, int cap) {
        edges.emplace_back(Edge(from, to, cap, 0));
        edges.emplace_back(Edge(to, from, 0, 0));
        m = int(edges.size());
        G[from].emplace_back(m-2);
        G[to].emplace_back(m-1);
    }
    bool BFS() {
        memset(vis, 0, sizeof(vis));
        memset(d, 0, sizeof(d));
        queue<int> q;
		while (!q.empty()) q.pop();
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = 0; i < int(G[x].size()); ++i) {
                Edge &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    Type DFS(int x, Type a) {
        if (x == t || a == 0) return a;
        Type flow = 0, f;
        for (int &i = cur[x]; i < int(G[x].size()); ++i) { //从上次考虑的弧
            Edge &e = edges[G[x][i]];
            if (d[x]+1 == d[e.to] && (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;
    }
    Type Maxflow(int s, int t) {
        this->s = s; this->t = t;
        Type flow = 0;
        while (BFS()) {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, INF);
        }
        return flow;
    }
    #undef Type
}dicnic;
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    while(cin>>n){
        dicnic.init(600);
        int tot=0, sum=0;
        for(int i=1; i<=n; ++i){
            for(int j=1; j<=n; ++j){
                cin>>mat[i][j];
                sum+=mat[i][j];
                num[i][j]=++tot;
            }
        }
        for(int i=1; i<=n; ++i){
            for(int j=1; j<=n; ++j){
                if((i+j)%2==0){
                    dicnic.addEdge(0, num[i][j], mat[i][j]);
                    if(i>1) dicnic.addEdge(num[i][j], num[i-1][j], INF);
                    if(i<n) dicnic.addEdge(num[i][j], num[i+1][j], INF);
                    if(j>1) dicnic.addEdge(num[i][j], num[i][j-1], INF);
                    if(j<n) dicnic.addEdge(num[i][j], num[i][j+1], INF);
                } else{
                    dicnic.addEdge(num[i][j], 500, mat[i][j]);
                }
            }
        }
        cout<<sum-dicnic.Maxflow(0, 500)<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值