传送门
源点 s s s为 1 1 1,汇点 t t t为 2 ∗ n + 2 2*n+2 2∗n+2
一个点 x i x_i xi拆成 x i 1 , x i 2 x_{i1},x_{i2} xi1,xi2, x i 1 和 1 相 连 , x i 2 和 2 ∗ n + 2 相 连 x_{i1}和1相连,x_{i2}和2*n+2相连 xi1和1相连,xi2和2∗n+2相连.
对于边 ( i , j ) (i,j) (i,j),连接 x i 1 x_{i1} xi1和 x j 2 x_{j2} xj2, x j 1 x_{j1} xj1和 x i 2 x_{i2} xi2.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<queue>
#include <iostream>
using namespace std;
using std::min;
using std::queue;
#define MAXN 100050
#define MAXM 100005
int n,m,s,t;
struct{
int to;
int val;
int nxt;
}edge[MAXM*2];
int edgecnt=1;
int head[MAXN];
int vis[MAXN];
int d[MAXN];
void addedge(int u,int v,int w)
{
edge[++edgecnt].to=v;
edge[edgecnt].val=w;
edge[edgecnt].nxt=head[u];
head[u]=edgecnt;
}
void init()
{
edgecnt=1;
for(int i=1;i<=2*n+2;i++)
head[i]=0;
}
bool bfs()
{
for(int i=1;i<=2*n+2;i++)
vis[i]=0;
vis[s]=1;
queue<int>q;
q.push(s);
while(!q.empty())
{
int now=q.front();q.pop();
for(int i=head [now];i;i=edge[i].nxt)
{
if(!vis[edge[i].to]&&edge[i].val)
{
vis[edge[i].to]=vis[now]+1;
q.push(edge[i].to);
}
}
}
return vis[t];
}
int dinic(int u,int flow)
{
if(u==t)
return flow;
int out=0;
for(int p=head[u];p and flow;p=edge[p].nxt){
int v=edge[p].to;
if(edge[p].val&&vis[u]+1==vis[v])
{
int res=dinic(v,min(flow,edge[p].val));
edge[p].val-=res;
edge[p^1].val+=res;
flow-=res;
out+=res;
}
}
if(out==0)
vis[u]=0;
return out;
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
init();
int check=0;
for(int i=1;i<=n;i++)
scanf("%d",d+i);
s=1;
t=2*n+2;
for(int i=1;i<=n;i++)
{
int x=2*i;
check+=d[i];
addedge(s,x,d[i]);
addedge(x,s,0);
addedge(x^1,t,d[i]);
addedge(t,x^1,0);
}
for (int i = 1; i <= m; i++) {
int a, b;
scanf("%d%d", &a, &b);
int x=2*a;
int y=2*b;
addedge(x, y^1, 1);
addedge(y^1, x, 0);
addedge(y, x^1, 1);
addedge(x^1, y, 0);
}
int ans = 0;
while (bfs())
ans += dinic(s, 2e9);
if(ans==check)
printf("YES\n");
else
printf("NO\n");
}
}