題目鏈接: http://codeforces.com/gym/102419/problem/H
題意:
2000個點,2000條邊,無重邊無自環的無向圖,現在要你把這些無向邊變成有向邊,使得每個點的入度爲給你的數組 ,如果爲 則任意入度即可。
做法:
兩種做法,第一種是費用流做法, 表示點, 表示邊,我們將邊也看成點,從原點到所有點連一條邊,如果這個 不爲 則連接邊流量爲 ,費用爲 ,否則就是 ,這樣的話就可以優先跑需要的點,並且度爲無限的點不會干擾到最後結果。然後驗證一下對不對就行了。
還有一種最大匹配做法,二分圖,把邊當成點,做匈牙利匹配即可,代碼不是自己寫的就不貼了。
代碼
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=4005;
const int maxm=80005;
const int inf=0x3f3f3f3f;
int dis[maxn],a[maxn],u[maxn],v[maxn];
int vis[maxn],pre[maxn];
int head[maxn],cnt,ed[maxm];
int n,m,sp,tp;
ll ans=0;
struct node{
int to,cap,cost,next;
}e[maxm];
void add(int from,int to,int cap,int cost){
e[cnt].to=to; e[cnt].cap=cap;
e[cnt].cost=cost; e[cnt].next=head[from];
head[from]=cnt++;
e[cnt].to=from; e[cnt].cap=0;
e[cnt].cost=-cost; e[cnt].next=head[to];
head[to]=cnt++;
}
bool spfa(int s,int t,int &flow,int &cost){
queue<int> q;
memset(dis,inf,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
dis[s]=0; q.push(s);
vis[s]=1;
int d=inf;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(e[i].cap>0&&dis[v]>dis[u]+e[i].cost){
dis[v]=dis[u]+e[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
if(dis[t]==inf){
return false;
}
for(int i=pre[t];~i;i=pre[e[i^1].to]){
d=min(d,e[i].cap);
}
for(int i=pre[t];~i;i=pre[e[i^1].to]){
e[i].cap-=d;
e[i^1].cap+=d;
cost+=e[i].cost*d;
}
flow+=d;
return true;
}
pii mcmf(int s,int t){
int flow=0,cost=0;
while(spfa(s,t,flow,cost)){
//cout<<flow<<" "<<cost<<endl;
}
return {flow,cost};
}
int main(){
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
sp=0;tp=n+m+1;
int sum=0;
rep(i,1,n){
int x; scanf("%d",&x);
if(x!=-1) add(sp,i,x,-1),sum+=x;
else add(sp,i,m,0);
}
rep(i,1,m){
add(n+i,tp,1,0);
scanf("%d%d",&u[i],&v[i]);
ed[i]=cnt;
add(u[i],i+n,1,0);
add(v[i],i+n,1,0);
}
pii ret=mcmf(sp,tp);
if(ret.first==m&&ret.second==-sum){
printf("YES\n");
rep(i,1,m){
if(e[ed[i]].cap==1) printf("%d %d\n",u[i],v[i]);
else printf("%d %d\n",v[i],u[i]);
}
}
else printf("NO\n");
return 0;
}