等刷网络流的时候再继续更新
最小割边集&&路径输出
先脑补一下
题目要我们求出以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;
}