您的位置:首页 > 其它

51nod 1442 士兵的旅行(最大流)

2017-10-27 12:34 260 查看
经典网络流模型。虚拟源点,汇点,拆点。拆点是因为每个士兵只能走一步。拆点后可以保证士兵只能走一步远。然后判断是否满流和移动前人数总和是否等于移动后人数总和。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1010;
const int INF = 0x7fffffff;
struct edge
{
int to,cap,rev;
};
vector<edge> G[MAXN];
int level[MAXN];
int iter[MAXN];

void addedge(int from, int to, int cap)
{
G[from].push_back((edge){to,cap,G[to].size()});
G[to].push_back((edge){from,0,G[from].size()-1});
}

//先分层,然后在分层图上dfs
void bfs(int s)
{
memset(level, -1, sizeof(level));
queue<int> que;
level[s] = 0;
que.push(s);
while(!que.empty())
{
int v = que.front();
que.pop();
for(int i = 0; i < G[v].size(); ++i)
{
edge& e = G[v][i];
if(e.cap > 0 && level[e.to] < 0)
{
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
}

int dfs(int v, int t, int f)
{
if(v == t) return f;
for(int &i = iter[v]; i < G[v].size(); ++i)
{
edge &e = G[v][i];
if(e.cap > 0 && level[v] < level[e.to])
{
int d = dfs(e.to, t, min(f, e.cap));
if(d > 0)
{
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}

int maxFlow(int s, int t)
{
int flow = 0;
while(true)
{
bfs(s);
if(level[t] < 0) return flow;
memset(iter,0,sizeof(iter));
int f;
while((f = dfs(s,t,INF)) > 0)
flow += f;
}
}

int n,m;
int a[MAXN];
int b[MAXN];
int main()
{
scanf("%d %d",&n,&m);
int sum1 = 0, sum2 = 0;
for(int i = 1; i <= n; ++i)
{
scanf("%d",&a[i]);
sum1 += a[i];
addedge(0,i,a[i]);
addedge(i,i+n,INF);
}
for(int i = 1; i <= n; ++i)
{
scanf("%d",&b[i]);
sum2 += b[i];
addedge(i+n,2*n+1,b[i]);
}
int u,v;
for(int i = 1; i <= m; ++i)
{
scanf("%d %d",&u,&v);
addedge(u,v+n,INF);
addedge(v,u+n,INF);
}
int res = 0;
res = maxFlow(0,n*2+1);
if(res != sum1 || sum1 != sum2)
printf("NO\n");
else
printf("YES\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: