HDU 4289 Control

时间:2023-03-09 08:29:31
HDU 4289  Control

最小割

一个点拆成两个 AddEdge(i,i+N,x);

原图中的每条边这样连 AddEdge(u+N,v,INF); AddEdge(v+N,u,INF);

S是源点,t+N是汇点。最大流就是答案。

#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std; const int maxn=+;
const int INF=0x7FFFFFFF; struct Edge
{
int from,to,cap,flow;
};
vector<Edge>edges;
vector<int>G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
int n,m,s,t; //求出层次网络
bool BFS()
{
memset(vis,,sizeof(vis));
queue<int>Q;
Q.push(s);
d[s]=;
vis[s]=;
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for(int i=; i<G[x].size(); i++)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=;
d[e.to]=d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
} //加边
void AddEdge(int from,int to,int cap)
{
Edge r;
r.from=from;
r.to=to;
r.cap=cap;
r.flow=;
edges.push_back(r);
Edge d;
d.from=to;
d.to=from;
d.cap=;
d.flow=;
edges.push_back(d);
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} //每个阶段来一次DFS增广
int DFS(int x,int a)
{
if(x==t||a==) return a;
int flow=,f;
for(int i=cur[x]; i<G[x].size(); i++)
{
Edge& e=edges[G[x][i]];
if(d[x]+==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>)
{
e.flow+=f;
edges[G[x][i]^].flow-=f;
flow+=f;
a-=f;
if(a==) break;
}
}
return flow;
} //多个阶段,多次建立层次网络。
int Maxflow(int ss,int tt)
{
int flow=;
while(BFS())
{
memset(cur,,sizeof(cur));
flow+=DFS(ss,INF);
}
return flow;
} int N,M;
int main()
{
while(~scanf("%d%d",&N,&M))
{
scanf("%d%d",&s,&t);
s=s;
t=t+N;
edges.clear();
for(int i=; i<maxn; i++) G[i].clear();
for(int i=; i<=N; i++)
{
int x;
scanf("%d",&x);
AddEdge(i,i+N,x);
}
for(int i=; i<=M; i++)
{
int u ,v;
scanf("%d%d",&u,&v);
AddEdge(u+N,v,INF);
AddEdge(v+N,u,INF);
}
printf("%d\n",Maxflow(s,t));
}
return ;
}