H. In-degree(网络流 图论)

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]);
            }
        }
    }
}



你可能感兴趣的:(图论/搜索)