poj 2135 最小费用流

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define SIZE 1010
const int inf = 100000000;
struct node{
	int s,t,f,w;
	int next;
}edge[100010];
int head[2010];
int mincost,tot;
int s,t,pre[2010];
void add(int s,int t,int w,int f)
{
	edge[tot].f=f;
	edge[tot].w=w;
	edge[tot].t=t;
	edge[tot].s=s;
	edge[tot].next=head[s];
	head[s]=tot++;
}
void addedge(int s,int t,int w,int f)
{
	add(s,t,w,f);
	add(t,s,-w,0);
}
int n;
bool spfa()
{
    bool vis[SIZE];
    memset(vis,false,sizeof(vis));
    int d[SIZE];
    int i=n+2;
    while(i--)d[i]= inf;
    d[s]=0;
    vis[s]=true;
    queue<int >Q;
    Q.push(s);
    pre[s]=-1;
    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        vis[u]=false;
		
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            if(edge[i].f>0&&d[u]+edge[i].w<d[edge[i].t])
            {
                d[edge[i].t]=d[u]+edge[i].w;
                pre[edge[i].t]=i;
                if(!vis[edge[i].t])
                {
                    Q.push(edge[i].t);
                    vis[edge[i].t]=true;
                }
            }
        }
    }
    if(d[t]==inf)
		return false;
    return true;
}   
void solve()
{
	for(int i=pre[t];i!=-1;i=pre[edge[i].s])
	{
		edge[i].f-=1;
		edge[i^1].f+=1;
		mincost+=edge[i].w;
	}
}
int main()
{
	int m,cases=1;
    while(scanf("%d%d",&n,&m),(n||m))
	{
		s=0;t=n+1;
		tot=0;
		mincost=0;
		memset(head,-1,sizeof(head));
		for(int i=0;i<m;i++)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			a++,b++;
			addedge(a,b,c,1);
			addedge(b,a,c,1);
		}
		addedge(s,1,0,2);
		addedge(n,t,0,2);
		while(spfa())
		{
			solve();
		}
   	    printf("%d\n",mincost);
	}
    return 0;
}

 

从起点走到终点,再从终点走到起点,不能有重复的路径

不能单纯的求最短路径两遍,因为第一次选的点会影响第二次走最短路的选择

因为每条边只能选一次,所以给每条边一个容量1,即只能流一次,费用为路径的长度

然后利用最小费用流来求解

 

posted @ 2011-11-24 23:49  Because Of You  Views(607)  Comments(0Edit  收藏  举报