2023.1.12 有源汇上下界最大流简笔

警示

2023.1.12

[模板]有源汇上下界最大流


错误点:

  1.建边方法简便:靠近于用u,v,w建边,不要冗杂多余(9-17行)

  2.算法注意点:首先抽出每条边的下界(每条边边权 = 上界 - 下界),建立虚拟源汇点进行dinic,答案得出后虚拟源点到汇点的流则为可行流,若虚拟源点的流出边有一个没有满流,则无解

         其次在原图上进行dinic直到没有增广路为止,二答案相加则为最大流答案。

  1 #include<bits/stdc++.h>
  2 #define int long long
  3 using namespace std;
  4 const int N = 1e5 + 5,inf = 0x7fffffff;
  5 struct Edge{
  6     int l,r,w,v,u,next;
  7 }e[N * 2];
  8 int head[N],n,m,g[N],c,p,ans = 0,tot = 1,d[N],vis[N],nw[N],st = 1,ed = n + m + 2,in[N],out[N];
  9 inline void add(int x,int y,int w)
 10 {
 11     ++tot;
 12     e[tot].u = x;
 13     e[tot].w = w;
 14     e[tot].v = y;
 15     e[tot].next = head[x];
 16     head[x] = tot;
 17 }
 18 inline void init()
 19 {
 20     for(int i=1;i<=tot;i++)
 21     {
 22         if(e[i].l == 0 && e[i].r == 0) continue;
 23         e[i].w = e[i].r - e[i].l;
 24     }
 25     for(int i=1;i<=n + m + 2;i++)
 26     {
 27         if(in[i] > out[i])
 28         {
 29             add(n + m + 3,i,in[i] - out[i]);
 30             e[tot].w = in[i] - out[i];
 31             add(i,n + m + 3,0);
 32         }
 33         if(out[i] > in[i])
 34         {
 35             add(i,n + m + 4,out[i] - in[i]);
 36             e[tot].w = out[i] - in[i];
 37             add(n + m + 4,i,0);
 38         }
 39     }
 40 }
 41 inline bool bfs()
 42 {
 43     for(int i=1;i<=n + m + 4;i++) d[i] = 0x7fffffff;
 44     queue <int> q;
 45     while(!q.empty()) q.pop();
 46     q.push(st);
 47     d[st] = 1;
 48     nw[st] = head[st];
 49     while(!q.empty())
 50     {
 51         int now = q.front();
 52         q.pop();
 53         for(int i = head[now];i;i = e[i].next)
 54         {
 55             int to = e[i].v;
 56             if(e[i].w <= 0 || d[to] < 0x7fffffff) continue;
 57             nw[to] = head[to];
 58             d[to] = d[now] + 1;
 59             q.push(to);
 60         }
 61     }
 62     if(d[ed] < 0x7fffffff) return 1;
 63     return 0;
 64 }
 65 inline int dinic(int x,int flow)
 66 {
 67     if(x == ed) return flow;
 68     int rest = flow;
 69     for(int i = nw[x];i && rest;i = e[i].next)
 70     {
 71         nw[x] = i;
 72         int to = e[i].v;
 73         if(d[to] != d[x] + 1 || e[i].w <= 0) continue;
 74         int k = dinic(to,min(rest,e[i].w));
 75         if(!k) d[to] = inf;
 76         rest -= k;
 77         e[i].w -= k;
 78         e[i ^ 1].w += k;
 79     }
 80     return flow - rest;    
 81 }
 82 signed main()
 83 {    
 84     while(cin>>n>>m)
 85     {
 86         memset(in,0,sizeof(in));
 87         memset(out,0,sizeof(out));
 88         tot = 1;
 89         memset(head,0,sizeof(head));
 90         memset(nw,0,sizeof(nw));
 91         ans = 0;
 92         int t,l,r;
 93         for(int i=1;i<=m;i++) 
 94         {
 95             cin>>g[i];
 96         }
 97         for(int i=1;i<=n;i++)
 98         {
 99             cin>>c>>p;
100             for(int j=1;j<=c;j++)
101             {
102                 cin>>t>>l>>r;
103                 t++;
104                 add(i + 1,n + t + 1,r - l);
105                 add(n + t + 1,i + 1,0);
106                 out[i + 1] += l;
107                 in[n + t + 1] += l;
108             }
109             add(1,i + 1,p);
110             add(i + 1,1,0);
111         }
112         for(int i=1;i<=m;i++)
113         {
114             add(i + n + 1,n + m + 2,inf - g[i]);
115             add(n + m + 2,i + n + 1,0);
116             out[i + n + 1] += g[i];
117             in[n + m + 2] += g[i];
118         }
119         st = n + m + 3;ed = n + m + 4;
120         init();
121         add(n + m + 2,1,inf);
122         add(1,n + m + 2,0);
123         int flow = 0;
124         while(bfs())
125             while(flow = dinic(st,inf)) 
126                 flow = 0;
127         int flag = 1;
128         ans += (inf - e[tot - 1].w);
129         for(int i = head[st];i;i = e[i].next)
130             if(e[i].w > 0) 
131                 flag = 0;
132         if(flag == 0) 
133         {
134             cout<<-1<<endl<<endl;
135             continue;
136         }
137         e[tot].w = 0;
138         e[tot - 1].w = 0;
139         st = 1;
140         ed = n + m + 2;
141         flow = 0;
142         while(bfs())
143             while(flow = dinic(st,inf))
144                 ans += flow;
145         cout<<ans<<endl<<endl;
146     }
147     return 0;
148 }

 

posted @ 2023-01-12 17:13  The_Last_Candy  阅读(15)  评论(0编辑  收藏  举报