http://codeforces.com/gym/102419/problem/H
题意:
给出一个无向图,和每个点的入度(-1则不要求),使之变为有向图满足要求。
解析:
x到ep连边:流量为x的入度,花费-1
sp到边连:流量为1,花费0
边到两个端点连边:流量1,花费0
如果x不要求:流量m,花费0
这样保证花费最小的时候每个点都满足入度条件。
方案输出为:查看反馈网络的流量,如果有流量,说明这条边被选中。
代码:
/*
* Author : Jk_Chen
* Date : 2020-03-28-16.32.57
*/
#include
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=1e5+9;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
const int inf=0x3f3f3f3f;
const LL infll=1e18;
const int N=4e5+9,M=2e6+9;
int head[N],nex[M],to[M],val[M],cost[M],now;
void add(int a,int b,int v,int c){// 反边流量0、花费-c
to[++now]=b;val[now]=v;cost[now]=c;nex[now]=head[a];head[a]=now;
to[++now]=a;val[now]=0;cost[now]=-c;nex[now]=head[b];head[b]=now;
}
//*********************
int sp,ep,dis[N];
bool vis[N];
int pre[N];
bool SPFA(int &flow,int &cos){
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
for(int i=0;i<N;i++)dis[i]=inf;
queue<int>Q;
dis[sp]=0;vis[sp]=1;Q.push(sp);
int d=inf;
while(!Q.empty()){
int p=Q.front();Q.pop();
vis[p]=0;
for(int i=head[p];~i;i=nex[i]){
int u=to[i];
if(val[i]>0&&dis[u]-cost[i]>dis[p]){
dis[u]=dis[p]+cost[i];
pre[u]=i;
if(!vis[u]){
vis[u]=1;Q.push(u);
}
}
}
}
if(dis[ep]==inf)return 0;
for(int i=pre[ep];~i;i=pre[to[i^1]]){
d=min(d,val[i]);
}
for(int i=pre[ep];~i;i=pre[to[i^1]]){
val[i]-=d;
val[i^1]+=d;
cos+=cost[i]*d;
}
flow+=d;
return 1;
}
pill MinCost(){
int flow=0,cost=0;
while(SPFA(flow,cost)){}
return {flow,cost};
}
void init(){
now=-1;//要求第一条边为0
memset(head,-1,sizeof(head));
}
int x[N],y[N],fg[N];
int main(){
init();
int n=rd,m=rd;
sp=m+n+1;ep=n+m+2;
int sum=0;
rep(i,1,n){
int in=rd;
if(in!=-1){
sum+=in;
add(i,ep,in,-1);
}
else
add(i,ep,m,0);
}
rep(i,1,m){
x[i]=rd,y[i]=rd;
add(sp,n+i,1,0);
add(n+i,x[i],1,0);
fg[i]=now;//反边
add(n+i,y[i],1,0);
}
auto ans=MinCost();
// test(ans);
if(ans.fi!=m||ans.se!=-sum){
puts("NO");
}
else{
puts("YES");
rep(i,1,m){
if(val[fg[i]]){
printf("%d %d\n",y[i],x[i]);
}
else{
printf("%d %d\n",x[i],y[i]);
}
}
}
}