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,即只能流一次,费用为路径的长度

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

 

你可能感兴趣的:(poj)