POJ 2135 Farm Tour【最小费用最大流】

题意: 有一个有 N 个节点的无向图,要求找出两条从1 节点 到 n 节点两条最短且不同的路径,求出其长度和。

分析: 由于是两条不同的路径,可以用最小费用最大流,因为是有重边,所以要用邻接表存储边。

         建图:

         建立一个源点 s = 0

         在 s 和 1 节点之间加一条容量为 2 费用为 0 的边,

         建立一个汇点 u = n+1

         在 n 和 u 之间加一条容量为 2 费用为 0 的边,

         两两节点如果连通,就在之间加一条 容量为 1,费用为边的长度的双向边。

 

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define INF 0x1f1f1f1f
#define min(a,b)(a)<(b)?(a):(b)
#define max(a,b)(a)>(b)?(a):(b)
struct node
{
    int next,from,to,w,c;
}e[100010];
int tot;
int head[1010];
void add(int st,int u,int wi,int flow)
{
    e[tot].from=st;
    e[tot].w=wi;
    e[tot].c=flow;
    e[tot].to=u;
    e[tot].next=head[st];
    head[st]=tot++;
}
int q[100010];
int pre[1010];
int dis[1010];
int v[1010];
int s,t;
int spfa()
{
    int i,x,front,rear,k;
    front=rear=0;
    for(i=0;i<=t;i++)
        dis[i]=INF;
    clr(v);
    pre[s]=-1;
    q[rear++]=s;
    dis[s]=0;
    v[s]=1;
    while(front<rear)
    {
        x=q[front++];
        v[x]=0;
        for(i=head[x];i!=-1;i=e[i].next)
        {
            k=e[i].to;
            if(e[i].c&&dis[x]+e[i].w<dis[k])
            {
                dis[k]=dis[x]+e[i].w;
                pre[k]=i;
                if(!v[k])
                {
                    v[k]=1;
                    if(dis[k]<=dis[x]&&front>0)
                        q[--front]=k;
                    else q[rear++]=k;
                }
            }
        }
    }
    if(dis[t]!=INF)
        return 1;
    return 0;
}
int costflow()
{
    int tt=0;
    int tot=0,flow=0,u,minf=INF;
    while(spfa())
    {
        for(u=pre[t];u!=-1;u=pre[e[u].from])
            minf=min(minf,e[u].c);
        for(u=pre[t];u!=-1;u=pre[e[u].from])
        {
            e[u].c-=minf;
            e[u^1].c+=minf;
            flow+=e[u].w*minf;
        }
    }
    return flow;
}
int main()
{
    int m,n,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        tot=0;
        memset(head,-1,sizeof(head));
        s=0;
        t=n+1;
        add(s,1,0,2);
        add(1,s,0,2);
        add(n,t,0,2);
        add(t,n,0,2);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c,1);
            add(b,a,-c,0);
            add(b,a,c,1);
            add(a,b,-c,0);
        }
        printf("%d\n",costflow());
    }
    return 0;
}

 

posted @ 2012-08-11 12:38  'wind  阅读(238)  评论(0编辑  收藏  举报