网络流随笔

等刷网络流的时候再继续更新

最小割边集&&路径输出
先脑补一下 在这里插入图片描述
在这里插入图片描述
题目要我们求出以1为源点 2为汇点的最小割集
裸题了,Dinic跑完就dfs标记一下S集合和T集合 一个点一个占一边说明就是割边 有点🐕 卡输出格式的换行

#include <bits/stdc++.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define Re register int
using namespace std;
 ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}

const int N = 1e5 + 3, M = 5 * 1e6 + 3;
int x, y, z, o = 1, n, m, h, t, st, ed, Q[N], cur[N], dis[N], head[N],zhanv;
long long maxflow;
struct QAQ {
    int to, next, flow,u;
} a[M << 1];
inline void in(Re &x) {
    int f = 0;
    x = 0;
    char c = getchar();
    while (c < '0' || c > '9') f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    x = f ? -x : x;
}
inline void add(Re x, Re y, Re z) { a[++o].flow = z, a[o].to = y, a[o].next = head[x], head[x] = o;a[o].u=x; }
inline int bfs(Re st, Re ed) {                                 // bfs求源点到所有点的最短路
    for (Re i = 0; i <= n; ++i) cur[i] = head[i], dis[i] = 0;  //当前弧优化cur=head
    h = 1, t = 0, dis[st] = 1, Q[++t] = st;
    while (h <= t) {
        Re x = Q[h++], to;
        for (Re i = head[x]; i; i = a[i].next)
            if (a[i].flow && !dis[to = a[i].to]) {
                dis[to] = dis[x] + 1, Q[++t] = to;
                if (to == ed)
                    return 1;
            }
    }
    return 0;
}
inline int dfs(Re x, Re flow) {  // flow为剩下可用的流量
    if (!flow || x == ed)
        return flow;  //发现没有流了或者到达终点即可返回
    Re tmp = 0, to, f;
    for (Re i = cur[x]; i; i = a[i].next) {
        cur[x] = i;  //当前弧优化cur=i
        if (dis[to = a[i].to] == dis[x] + 1 && (f = dfs(to, min(flow - tmp, a[i].flow)))) {
            //若边权为0,不满足增广路性质,或者跑下去无法到达汇点,dfs返回值f都为0,不必执行下面了
            a[i].flow -= f, a[i ^ 1].flow += f;
            tmp += f;  //记录终点已经从x这里获得了多少流
            if (!(flow - tmp))
                break;
            // 1. 从st出来流到x的所有流被榨干。后面的边都不用管了,break掉。
            //而此时边i很可能还没有被榨干,所以cur[x]即为i。
            // 2. 下面儿子的容量先被榨干。不会break,但边i成了废边。
            //于是开始榨x的下一条边i',同时cur[x]被更新成下一条边i'
            //直至榨干从x上面送下来的水流结束(即情况1)。
        }
    }
    return tmp;
}
inline void Dinic(Re st, Re ed) {
    Re flow = 0;
    while (bfs(st, ed)) maxflow += dfs(st, inf);
}
ll vis[100006];
void dfs(ll u){
vis[u]=1;
for(int i=head[u];i!=0;i=a[i].next){
   ll v=a[i].to;
   if(vis[v]||a[i].flow<=0){continue;}
   dfs(v);
}
}
void cle(){

memset(head,0,sizeof(head));
maxflow=0;
o=1;

}
signed main(){

while(scanf("%lld%lld",&n,&m)!=EOF){
if(n==0&&m==0){
    break;
}
cle();
for(int i=1;i<=m;i++){
   ll uu,vv,ww;
   read(uu);
   read(vv);
   read(ww);
   add(uu,vv,ww);
//   add(vv,uu,0);
   add(vv,uu,ww);
}

st=1;
ed=2;
Dinic(st,ed);
//printf("Q%lld\n",maxflow);
memset(vis,0,sizeof(vis));
dfs(1);

for(int i=2;i<=o;i=i+2){
ll u=a[i].u;
ll v=a[i].to;
if(vis[u]&&!vis[v]||!vis[u]&&vis[v]){
    printf("%lld %lld\n",u,v);
}

}
  putchar(10);
}
return 0;
}

蜥蜴大逃脱&&建图最大流
每个格子拆成两个点,点1为入, 点2为出。 对于每个初始有蜥蜴的格子我们把它连在超级源点上面,边容为1 ,对于可以从当前格子跳到安全区域的我们把它连在超级汇点上边容INF 拆点连接边容为限制跳跃次数
如果当前格子不能跳到安全地带,那么就把它连接到其他可以到达的距离小于D的拆点格子上面 跑一遍最大流

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#include<iostream>
#define INF 1e9
using namespace std;
const int maxn =1000+10;
 
struct Edge
{
    int from,to,cap,flow;
    Edge(){}
    Edge(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl){}
};
 
struct Dinic
{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    int cur[maxn];
    int d[maxn];
    bool vis[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;
        Q.push(s);
        memset(vis,0,sizeof(vis));
        d[s]=0;
        vis[s]=true;
        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)
                {
                    d[e.to]=1+d[x];
                    vis[e.to]=true;
                    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,d,src,dst;
        int sum=0;//蜥蜴数
        scanf("%d%d",&n,&d);
        for(int i=1;i<=n;i++)
        {
            string s;
            cin>>s;
            if(i==1)//第一次
            {
                m = s.size();
                src=0, dst=2*n*m+1;
                DC.init(2*n*m+2,src,dst);
            }
            for(int j=0;j<s.size();++j)if(s[j]-'0'>0)
            {
                int id = (i-1)*m+j+1;//当前点编号
                DC.AddEdge(id, id+n*m, s[j]-'0');
                if(i<=d || i+d>n || j<d || j+d>=m)//当前格子能直接跳出棋盘
                {
                    DC.AddEdge(id+n*m,dst,INF);
                }
                else //不能直接跳出去
                {
                    for(int k=1;k<=n;k++)
                    for(int h=0;h<m;h++)
                    {
                        int id2= (k-1)*m+h+1;
                        if(id==id2) continue;
                        if(abs(i-k)+abs(j-h)<= d) DC.AddEdge(id+n*m,id2,INF);
                    }
                }
            }
        }
        for(int i=1;i<=n;++i)
        {
            string s;
            cin>>s;
            for(int j=0;j<s.size();++j)
            {
                int id = (i-1)*m+j+1;//当前点编号
                if(s[j]=='L')
                {
                    ++sum;
                    DC.AddEdge(src,id,1);
                }
            }
        }
        int ans = sum-DC.max_flow();
        if(ans==0) printf("Case #%d: no lizard was left behind.\n",kase);
        else if(ans==1) printf("Case #%d: 1 lizard was left behind.\n",kase);
        else printf("Case #%d: %d lizards were left behind.\n",kase,ans);
    }
    return 0;
}

HDU多校 网络流 07 Go Runing
在这里插入图片描述
2020-7-30 刷网络流到四点 听说07是网络流,我就拿来练练手了,一发AC

主要是有个关系 看代成函数 x+ti -x+ti 相当于对应着ti时刻的位置xi 要满足两个点位的关系而且要使得学生人数最小 ,那不就是最小点覆盖吗
最小点覆盖值等于最大流 离散化建图跑一次就OK

#include <bits/stdc++.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define Re register int
using namespace std;
 ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}

const int N =2* 1e5 + 3, M = 5 * 1e6 + 3;
int x, y, z, o = 1, n, m, h, t, st, ed, Q[N], cur[N], dis[N], head[N],zhanv;
long long maxflow;
ll cnt;
struct QAQ {
    int to, next, flow;
} a[M << 1];
inline void in(Re &x) {
    int f = 0;
    x = 0;
    char c = getchar();
    while (c < '0' || c > '9') f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    x = f ? -x : x;
}
inline void add(Re x, Re y, Re z) { a[++o].flow = z, a[o].to = y, a[o].next = head[x], head[x] = o; }
inline int bfs(Re st, Re ed) {                                 // bfs求源点到所有点的最短路
    for (Re i = 0; i <= cnt*2+1; ++i) cur[i] = head[i], dis[i] = 0;  //当前弧优化cur=head
    h = 1, t = 0, dis[st] = 1, Q[++t] = st;
    while (h <= t) {
        Re x = Q[h++], to;
        for (Re i = head[x]; i; i = a[i].next)
            if (a[i].flow && !dis[to = a[i].to]) {
                dis[to] = dis[x] + 1, Q[++t] = to;
                if (to == ed)
                    return 1;
            }
    }
    return 0;
}
inline int dfs(Re x, Re flow) {  // flow为剩下可用的流量
    if (!flow || x == ed)
        return flow;  //发现没有流了或者到达终点即可返回
    Re tmp = 0, to, f;
    for (Re i = cur[x]; i; i = a[i].next) {
        cur[x] = i;  //当前弧优化cur=i
        if (dis[to = a[i].to] == dis[x] + 1 && (f = dfs(to, min(flow - tmp, a[i].flow)))) {
            //若边权为0,不满足增广路性质,或者跑下去无法到达汇点,dfs返回值f都为0,不必执行下面了
            a[i].flow -= f, a[i ^ 1].flow += f;
            tmp += f;  //记录终点已经从x这里获得了多少流
            if (!(flow - tmp))
                break;
            // 1. 从st出来流到x的所有流被榨干。后面的边都不用管了,break掉。
            //而此时边i很可能还没有被榨干,所以cur[x]即为i。
            // 2. 下面儿子的容量先被榨干。不会break,但边i成了废边。
            //于是开始榨x的下一条边i',同时cur[x]被更新成下一条边i'
            //直至榨干从x上面送下来的水流结束(即情况1)。
        }
    }
    return tmp;
}
inline void Dinic(Re st, Re ed) {
    Re flow = 0;
    while (bfs(st, ed)) maxflow += dfs(st, inf);
}

typedef pair<int, int>PII;
PII ar[300003];

int b[300003];
signed main()
{
    ll tp;
    read(tp);
    while(tp--){
        read(n);
        cnt =0;
        for (int i = 1; i <= n; i ++)
        {   ll t,xu;
            read(t);
            read(xu);

            ar[i].first = xu - t, ar[i].second = xu + t;
            b[++ cnt] = xu - t, b[++ cnt] = xu + t;
        }
        sort(b + 1, b + cnt + 1);
        cnt = unique(b + 1, b + cnt + 1) - (b + 1);
        o= 1;
        maxflow=0;
        for (int i = 0; i <= cnt + cnt + 1; i ++)
            head[i] = 0;

        for (int i = 1; i <= n; i ++)
        {
            ar[i].first = lower_bound(b + 1, b + cnt + 1, ar[i].first) - b;
            ar[i].second = lower_bound(b + 1, b + cnt + 1, ar[i].second) - b;
        }
        for (int i = 1; i <= n; i ++)
        {
            add(ar[i].first, ar[i].second + cnt, 1);
             add(ar[i].second + cnt,ar[i].first ,0);
        }
        st = 0, ed = cnt + cnt + 1;
        for (int i = 1; i <= cnt; i ++)
        {
            add(st, i, 1);
               add(i,st, 0);
            add(cnt + i, ed, 1);
               add(ed,cnt+i,0);
        }
        Dinic(st,ed);
        printf("%lld\n",maxflow);
    }
return 0;
}

网络流24题&&运输问题
本题涉及到最小费 最大费 ,存货点与超级源点建边 容量为存货量 - - 这题好无趣啊,裸题 ,建好了跑最小费,然后重新建边,容量为负,最终最小费取负就是最大费了

#include <bits/stdc++.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
//#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define Re register int
using namespace std;
const int N = 1e5, M = 2 * 1e6 + 3, inf = 2e9;
int x, y, z, w, o = 1, n, m, h, t, st, ed, cyf[N], pan[N], pre[N], dis[N], head[N];
ll mincost, maxflow;
struct QAQ {
    int w, to, next, flow;
} a[M << 1];
queue<int> Q;
inline void read(Re &x) {
    int f = 0;
    x = 0;
    char c = getchar();
    while (c < '0' || c > '9') f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    x = f ? -x : x;
}
inline void add(Re x, Re y, Re z, Re w) {
    a[++o].flow = z, a[o].w = w, a[o].to = y, a[o].next = head[x], head[x] = o;
}
inline void add_(Re a, Re b, Re flow, Re w) { add(a, b, flow, w), add(b, a, 0, -w); }
inline int SPFA(Re st, Re ed) {
    for (Re i = 0; i <= n + 1 + m; ++i) dis[i] = inf, pan[i] = 0;  //有多少个点就初始化到那个地方去
    Q.push(st), pan[st] = 1, dis[st] = 0, cyf[st] = inf;
    while (!Q.empty()) {
        Re x = Q.front();
        Q.pop();
        pan[x] = 0;
        for (Re i = head[x], to; i; i = a[i].next)
            if (a[i].flow && dis[to = a[i].to] > dis[x] + a[i].w) {
                dis[to] = dis[x] + a[i].w, pre[to] = i;
                cyf[to] = min(cyf[x], a[i].flow);
                if (!pan[to])
                    pan[to] = 1, Q.push(to);
            }
    }
    return dis[ed] != inf;
}
inline void EK(Re st, Re ed) {
    while (SPFA(st, ed)) {
        Re x = ed;
        maxflow += cyf[ed], mincost += (ll)cyf[ed] * dis[ed];
        while (x != st) {  //和最大流一样的更新
            Re i = pre[x];
            a[i].flow -= cyf[ed];
            a[i ^ 1].flow += cyf[ed];
            x = a[i ^ 1].to;
        }
    }
}

ll cu[200];
ll need[200];
ll cost[210][210];
signed main() {
    read(m);  //仓库
    read(n);  // 商店
    for (int i = 1; i <= m; i++) {
        read(cu[i]);
        add_(0, i, cu[i], 0);
    }
    for (int i = 1; i <= n; i++) {
        read(need[i]);
        add_(i + m, m + n + 1, need[i], 0);
    }

    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            read(cost[i][j]);
            add_(i, j + m, inf, cost[i][j]);
        }
    }
    st = 0;
    ed = n + m + 1;
    EK(st, ed);
    printf("%lld\n", mincost);
    memset(head, 0, sizeof(head));
    o = 1;
    mincost = 0;
    for (int i = 1; i <= m; i++) {
        //  read(cu[i]);
        add_(0, i, cu[i], 0);
    }
    for (int i = 1; i <= n; i++) {
        //  read(need[i]);
        add_(i + m, m + n + 1, need[i], 0);
    }
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            //  read(cost[i][j]);
            add_(i, j + m, inf, -cost[i][j]);
        }
    }
    st = 0;
    ed = n + m + 1;
    EK(st, ed);
    printf("%lld\n", -mincost);

    return 0;
}

网络流24题&&分配问题
最小费最大费裸题- - 参考上文代码吧
网络流24题&&负载平衡
对每个点 计算一下它跟平均值差多少,如果多余平均值则建立超级源点的边,否则建立汇点的边, 然后相邻的城市 建立无向边 费用为cost 源点汇点的边费用为0 注意这是个环 所以 我们要特殊处理n与1的关系
然后跑一次最小费就好了

#include <bits/stdc++.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
//#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define Re register int
using namespace std;
const int N = 5 * 1e5, M = 2 * 1e6 + 3, inf = 2e9;
int x, y, z, w, o = 1, n, m, h, t, st, ed, cyf[N], pan[N], pre[N], dis[N], head[N];
ll mincost, maxflow;
struct QAQ {
    int w, to, next, flow;
} a[M << 1];
queue<int> Q;
inline void read(Re &x) {
    int f = 0;
    x = 0;
    char c = getchar();
    while (c < '0' || c > '9') f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    x = f ? -x : x;
}
inline void add(Re x, Re y, Re z, Re w) {
    a[++o].flow = z, a[o].w = w, a[o].to = y, a[o].next = head[x], head[x] = o;
}
inline void add_(Re a, Re b, Re flow, Re w) { add(a, b, flow, w), add(b, a, 0, -w); }
inline int SPFA(Re st, Re ed) {
    for (Re i = 0; i <= n + 1; ++i) dis[i] = inf, pan[i] = 0;  //有多少个点就初始化到那个地方去
    Q.push(st), pan[st] = 1, dis[st] = 0, cyf[st] = inf;
    while (!Q.empty()) {
        Re x = Q.front();
        Q.pop();
        pan[x] = 0;
        for (Re i = head[x], to; i; i = a[i].next)
            if (a[i].flow && dis[to = a[i].to] > dis[x] + a[i].w) {
                dis[to] = dis[x] + a[i].w, pre[to] = i;
                cyf[to] = min(cyf[x], a[i].flow);
                if (!pan[to])
                    pan[to] = 1, Q.push(to);
            }
    }
    return dis[ed] != inf;
}
inline void EK(Re st, Re ed) {
    while (SPFA(st, ed)) {
        Re x = ed;
        maxflow += cyf[ed], mincost += (ll)cyf[ed] * dis[ed];
        while (x != st) {  //和最大流一样的更新
            Re i = pre[x];
            a[i].flow -= cyf[ed];
            a[i ^ 1].flow += cyf[ed];
            x = a[i ^ 1].to;
        }
    }
}

ll as[200];
signed main() {
    read(n);
    ll adds = 0;
    for (int i = 1; i <= n; i++) {
        read(as[i]);
        adds = adds + as[i];
    }
    adds = adds / n;
    for (int i = 1; i <= n; i++) {
        if (as[i] - adds < 0) {
            //需要进货
            add_(i, n + 1, adds - as[i], 0);
        }
        if (as[i] - adds > 0) {
            add_(0, i, as[i] - adds, 0);
        }
    }
    for (int i = 1; i <= n - 1; i++) {
        add_(i, i + 1, inf, 1);
        add_(i + 1, i, inf, 1);
    }
    add_(n, 1, inf, 1);
    add_(1, n, inf, 1);
    st = 0;
    ed = n + 1;
    EK(st, ed);
    printf("%lld", mincost);
    return 0;
}

网络流&& 建模 最大流
n个任务 M个机器 每个任务必须在si天开始做 要做pi天 而且必须在ei天前 完成,每个机器在一个时间只能处理一个任务(开始做就要做完,这个机器是不能用的)

#include <bits/stdc++.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define mp make_pair
#define pb push_back
#define sie size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define Re register int
using namespace std;
 ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}

const int N = 7*1e5 + 3, M = 5 * 1e6 + 3;
int x, y, z, o = 1, n, m, h, t, st, ed, Q[N], cur[N], dis[N], head[N],zhanv;
long long maxflow;
struct QAQ {
    int to, next, flow;
} a[M << 1];
inline void in(Re &x) {
    int f = 0;
    x = 0;
    char c = getchar();
    while (c < '0' || c > '9') f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    x = f ? -x : x;
}
inline void add(Re x, Re y, Re z) { a[++o].flow = z, a[o].to = y, a[o].next = head[x], head[x] = o; }
inline int bfs(Re st, Re ed) {                                 // bfs求源点到所有点的最短路
    for (Re i = 0; i <= 1000+n; ++i) cur[i] = head[i], dis[i] = 0;  //当前弧优化cur=head
    h = 1, t = 0, dis[st] = 1, Q[++t] = st;
    while (h <= t) {
        Re x = Q[h++], to;
        for (Re i = head[x]; i; i = a[i].next)
            if (a[i].flow && !dis[to = a[i].to]) {
                dis[to] = dis[x] + 1, Q[++t] = to;
                if (to == ed)
                    return 1;
            }
    }
    return 0;
}
inline int dfs(Re x, Re flow) {  // flow为剩下可用的流量
    if (!flow || x == ed)
        return flow;  //发现没有流了或者到达终点即可返回
    Re tmp = 0, to, f;
    for (Re i = cur[x]; i; i = a[i].next) {
        cur[x] = i;  //当前弧优化cur=i
        if (dis[to = a[i].to] == dis[x] + 1 && (f = dfs(to, min(flow - tmp, a[i].flow)))) {
            //若边权为0,不满足增广路性质,或者跑下去无法到达汇点,dfs返回值f都为0,不必执行下面了
            a[i].flow -= f, a[i ^ 1].flow += f;
            tmp += f;  //记录终点已经从x这里获得了多少流
            if (!(flow - tmp))
                break;
            // 1. 从st出来流到x的所有流被榨干。后面的边都不用管了,break掉。
            //而此时边i很可能还没有被榨干,所以cur[x]即为i。
            // 2. 下面儿子的容量先被榨干。不会break,但边i成了废边。
            //于是开始榨x的下一条边i',同时cur[x]被更新成下一条边i'
            //直至榨干从x上面送下来的水流结束(即情况1)。
        }
    }
    return tmp;
}
inline void Dinic(Re st, Re ed) {
    Re flow = 0;
    while (bfs(st, ed)) maxflow += dfs(st, inf);
}

struct pe{
ll pi;
ll si ;
ll ee;

}ff[700];
void cle(){

memset(head,0,sizeof(head));
o=1;
maxflow=0;
}
signed main(){
ll t;
ll ca=0;
read(t);
while(t--){
 ca++;
 read(n);
 read(m);
 ll flag=0;
 ll ok=0;
 cle();
 st=0;
 ed=1000+n;
 ll ma=-1;
 for(int i=1;i<=n;i++){
read(ff[i].pi);
read(ff[i].si);
read(ff[i].ee);
ma=max(ma,ff[i].ee);
ok=ok+ff[i].pi;
add(0,i,ff[i].pi);
add(i,0,0);
for(int j=ff[i].si;j<=ff[i].ee;j++){
  add(i,j+n,1);
  add(j+n,i,0);

}

}
for(int i=n+1;i<=n+ma;i++){
  add(i,ed,m);
  add(ed,i,0);
}

 Dinic(st,ed);

 if(maxflow==ok){
  printf("Case %lld: Yes\n",ca);
  printf("\n");
  continue;
 }
 else{
printf("Case %lld: No\n",ca);
printf("\n");
    continue;
 }
}
return 0;
}

判断满流&&离散化
跟上一题及其类似 - - 注意区间离散化 不然会崩

#include <bits/stdc++.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define Re register int
using namespace std;
 ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll tp;
const int N = 5*1e4, M = 5 * 1e6 + 3;
int x, y, z, o = 1, n, m, h, t, st, ed, Q[N], cur[N], dis[N], head[N],zhanv;
long long maxflow;
struct QAQ {
    int to, next, flow;
} a[M << 1];
inline void in(Re &x) {
    int f = 0;
    x = 0;
    char c = getchar();
    while (c < '0' || c > '9') f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    x = f ? -x : x;
}
inline void add(Re x, Re y, Re z) { a[++o].flow = z, a[o].to = y, a[o].next = head[x], head[x] = o; }
inline int bfs(Re st, Re ed) {                                 // bfs求源点到所有点的最短路
    for (Re i = 0; i <= tp; ++i) cur[i] = head[i], dis[i] = 0;  //当前弧优化cur=head
    h = 1, t = 0, dis[st] = 1, Q[++t] = st;
    while (h <= t) {
        Re x = Q[h++], to;
        for (Re i = head[x]; i; i = a[i].next)
            if (a[i].flow && !dis[to = a[i].to]) {
                dis[to] = dis[x] + 1, Q[++t] = to;
                if (to == ed)
                    return 1;
            }
    }
    return 0;
}
inline int dfs(Re x, Re flow) {  // flow为剩下可用的流量
    if (!flow || x == ed)
        return flow;  //发现没有流了或者到达终点即可返回
    Re tmp = 0, to, f;
    for (Re i = cur[x]; i; i = a[i].next) {
        cur[x] = i;  //当前弧优化cur=i
        if (dis[to = a[i].to] == dis[x] + 1 && (f = dfs(to, min(flow - tmp, a[i].flow)))) {
            //若边权为0,不满足增广路性质,或者跑下去无法到达汇点,dfs返回值f都为0,不必执行下面了
            a[i].flow -= f, a[i ^ 1].flow += f;
            tmp += f;  //记录终点已经从x这里获得了多少流
            if (!(flow - tmp))
                break;
            // 1. 从st出来流到x的所有流被榨干。后面的边都不用管了,break掉。
            //而此时边i很可能还没有被榨干,所以cur[x]即为i。
            // 2. 下面儿子的容量先被榨干。不会break,但边i成了废边。
            //于是开始榨x的下一条边i',同时cur[x]被更新成下一条边i'
            //直至榨干从x上面送下来的水流结束(即情况1)。
        }
    }
    return tmp;
}
inline void Dinic(Re st, Re ed) {
    Re flow = 0;
    while (bfs(st, ed)) maxflow += dfs(st, inf);
}
void cle(){
memset(head,0,sizeof(head));
o=1;
maxflow=0;
}
ll T[N];
ll aa[N],cc[N];
ll rnm=0;
signed main()
{
    while(scanf("%lld%lld",&n,&m)!=EOF)
    {
        cle();
        rnm=0;
        ll ad=0;
        tp=0;
        for(int i=1; i<=n; i++)
        {
            ll ne,ti;
            read(T[++rnm]); //  开始
            aa[i]=T[rnm];
            read(ne);//   需求量
            read(T[++rnm]); //  结束
            cc[i]=T[rnm];
            read(ti); // 单位T
            add(0,i,ne*ti);
            add(i,0,0);
            ad=ad+ne*ti;
        }
        sort( T+1, T+rnm+1 );
        int top = unique(T+1, T+rnm+1)-(T+1);
        tp = n+top+1;
        for( int i=1; i<=top; i++ )
        {
            add( n+i, tp, m*(T[i]-T[i-1]) );
            add( tp, n+i, 0 );
            for( int j=1; j<=n; j++ )
            {
                if( aa[j]<=T[i-1] && cc[j]>=T[i] )
                {
                    add( j, n+i, inf );
                    add(n+i,j,0);
                }
            }
        }
        st=0;
        ed=tp;
        Dinic(st,ed);
//printf("%lld %lld\n",maxflow,ad);
        if(maxflow!=ad)
        {
            printf("No\n");
            continue;
        }
        else
        {
            printf("Yes\n");
            continue;
        }

    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值