poj 2135 (基础费用流)

题意:从1到n再到1,每条边只能走一次,求最短距离。

建图:每条边只能走一次就是流量是1,添加源点与1相连,容量为2,费用为0,n与汇点相连容量为2,费用为0;

求增广路用SPFA最短路求,,






 

#include<stdio.h>
#include<queue>
#include<string.h>
const int N=1100;
const int inf=0x3fffffff;
using namespace std;
int cost[N],start,end,n,head[N],num,pre[N],vis[N];
struct edge
{
	int st,ed,cp,flow,next;
}e[N*N];
void addedge(int x,int y,int c,int w)
{
	e[num].st=x;e[num].ed=y;e[num].cp=c; e[num].flow=w;e[num].next=head[x];head[x]=num++;
	e[num].st=y;e[num].ed=x;e[num].cp=-c;e[num].flow=0;e[num].next=head[y];head[y]=num++;
}
int SPFA()
{
	int i,u,v;
	queue<int>Q;
	for(i=start;i<=end;i++)
	{cost[i]=inf;vis[i]=0;pre[i]=-1;}
	cost[start]=0;vis[start]=1;
	Q.push(start);	
	while(!Q.empty())
	{
		u=Q.front();
		Q.pop();vis[u]=0;
		for(i=head[u];i!=-1;i=e[i].next)
		{
			v=e[i].ed;
			if(e[i].flow>0&&cost[v]>cost[u]+e[i].cp)
			{
				pre[v]=i;
				cost[v]=cost[u]+e[i].cp;
				if(vis[v]==0)
				{
					vis[v]=1;
					Q.push(v);
				}
			}
		}
	}
	if(pre[end]==-1)
		return 0;
	return 1;
}
int mincost()
{
	int MINcost=0,maxflow=0,i,minflow;
	while(SPFA())
	{
		minflow=inf;
		for(i=pre[end];i!=-1;i=pre[e[i].st])
			if(minflow>e[i].flow)
				minflow=e[i].flow;
			maxflow+=minflow;
		for(i=pre[end];i!=-1;i=pre[e[i].st])
		{
			e[i].flow-=minflow;
			e[i^1].flow+=minflow;
			MINcost+=e[i].cp;
		}			
	}
	return MINcost;
}
int main()
{
	int i,x,y,c,m;
	while(scanf("%d%d",&n,&m)!=-1)
	{
		start=0;end=n+1;num=0;
		memset(head,-1,sizeof(head));
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&x,&y,&c);
			addedge(x,y,c,1);
			addedge(y,x,c,1);
		}
		addedge(start,1,0,2);
		addedge(n,end,0,2);
		printf("%d\n",mincost());
	}
	return 0;
}


 

 

转载于:https://www.cnblogs.com/james1207/p/3257978.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值