sgu 176 Flow construction--有源汇 有上下界 最小流

/*
SGU 176 Flow construction
题意:有些节点(编号1~n,1为源,n为汇)和管道,用来运输某种物质(substance)
某些管道必须满流,有些不必,找到一个最小流,满足要求
输入:
结束数目 管道数目
管道{
	管道前节点,后节点,最大流量,是否需要满流(1需要0不需要)
}

就是求一个最小流
http://blog.csdn.net/qq172108805/article/details/7802832
有最小流做法
*/
#include<stdio.h>  
#include<string.h>  
#define inf 0x7fffffff  
struct edge//边    
{    
    int u,v,f,next,b,c;
}e[15000];    
int head[110],in[110],s,t,ss,tt,yong,sum,bian[11000];  
int n,m; 
void ini()  
{  
    memset(head,-1,sizeof(head));  
    yong=0;  
    memset(in,0,sizeof(in));  
    s=1,t=n,ss=0,tt=t+1;
    sum=0;  
	memset(bian,0,sizeof(bian));
} 
void adde(int from,int to,int xia,int shang)//加边    
{   //加边    
    e[yong].u=from,e[yong].v=to,e[yong].f=shang-xia,e[yong].b=xia,e[yong].c=shang;    
    e[yong].next=head[from],head[from]=yong++;    
    //同时加它的退边    
    e[yong].u=to,e[yong].v=from,e[yong].f=0,e[yong].b=xia,e[yong].c=shang;    
    e[yong].next=head[to],head[to]=yong++;    
} 
void build()
{
	int i;    
    for(i=s;i<=t;++i)    
    {    
        if(in[i]>0)    
            adde(ss,i,0,in[i]);    
        else    
        {    
            adde(i,tt,0,-in[i]);    
            sum+=(-in[i]);    
        }    
    }   
}
int d[110],num[110];
int min(int a,int b){return a<b?a:b;}    
int sap_gap(int u,int f,int s,int t)//递归sap    
{    
    if(u==t)    
        return f;    
    int i,v,mind=t,last=f,cost;    
    for(i=head[u];i!=-1;i=e[i].next)    
    {    
        v=e[i].v;    
        int flow=e[i].f;    
        if(flow>0)//参考模版写的时候把flow写成了f    
        {    
            if(d[u]==d[v]+1)    
            {    
                cost=sap_gap(v,min(last,flow),s,t);    
                e[i].f-=cost;    
                e[i^1].f+=cost;    
                last-=cost;    
    
                if(d[s]>=t+1)    
                    return f-last;    
    
                if(last==0)    
                    break;    
            }    
            if(d[v]<mind)    
                mind=d[v];    
        }    
    }    
    
    if(last==f)    
    {    
        --num[d[u]];    
        if(num[d[u]]==0)    
            d[s]=t+1;    
        d[u]=mind+1;    
        ++num[d[u]];    
    }    
    return f-last;    
}    
int max_f(int s,int t)  
{  
    int f=0;    
    memset(d,0,sizeof(d));    
    memset(num,0,sizeof(num));    
    for(num[s]=t+1;d[s]<t+1;)    
        f+=sap_gap(s,inf,s,t);    
    return f;   
}
int main()
{
	int i,a,b,c,d,f1,f2,p;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		ini();
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d%d",&a,&b,&c,&d);
			if(d==0)
			{
				bian[i]=yong;
				adde(a,b,0,c);
			}else
			{
				bian[i]=yong;
				adde(a,b,c,c);
				in[a]-=c;
				in[b]+=c;
			}

		}
		build();
		f1=max_f(ss,tt);  
	    p=yong;  
		adde(t,s,0,inf);  
		f2=max_f(ss,tt); 
		if(f1+f2!=sum) printf("Impossible\n");
		else
		{
			printf("%d\n",e[p^1].f);
			for(i=1;i<m;++i)
			{
				printf("%d ",e[bian[i]].c-e[bian[i]].f);
			}
			printf("%d\n",e[bian[m]].c-e[bian[m]].f);
		}
	}
	return 0;
}

你可能感兴趣的:(sgu 176 Flow construction--有源汇 有上下界 最小流)