无向图的最小费用流,建图时可以分别加入两条边(u,v,w,c),(v,u,w,c),即当做两条有向边。
建立一个超级源点和超级汇点,容量为2,其余边容量为1,剩下的就是最小费用流的求解过程了。
POJ 2135
#include<iostream>
using namespace std;
struct edge
{
    
int u,v,next,f,w;
}e[
40010];
int n,m;
int mincost=0;
int p[2000];
int num=0;
int head[2000];
int s,t;
void add(int s,int t,int w,int c)
{
    e[num].f
=c;
    e[num].next
=head[s];
    head[s]
=num;
    e[num].u
=s;
    e[num].v
=t;
    e[num
++].w=w;
    
return ;
}
void addedge(int s,int t,int w,int c)
{
    add(s,t,w,c);
    add(t,s,
-w,0);
    
return ;
}
bool spfa()
{
    
int i,j;
    
int Q[2000],front(0),tail(0);
    
int d[2000];
    
bool ok[2000];
    memset(ok,
0,sizeof(ok));
    
for(i=0;i<=n+2;i++)
    {
        d[i]
=INT_MAX;
    }
    d[s]
=0;
    ok[s]
=1;
    p[s]
=-1;
    Q[
++tail]=s;
    
while(tail!=front)
    {
        i
=Q[++front];
        ok[i]
=0;
        
for(j=head[i];j!=-1;j=e[j].next)
        {
            
if(e[j].f>0&&d[i]+e[j].w<d[e[j].v])
            {
                d[e[j].v]
=d[i]+e[j].w;
                p[e[j].v]
=j;
                
if(!ok[e[j].v])
                {
                    Q[
++tail]=e[j].v;
                    ok[e[j].v]
=1;
                }
            }
        }
    }
    
if(d[t]<INT_MAX)
        
return 1;
    
else return 0;
}
int solve()
{
    
int i;
    
int minflow=INT_MAX;
    
for(i=p[t];i!=-1;i=p[e[i].u])
    {
        
if(minflow>e[i].f)
            minflow
=e[i].f;
    }
    
for(i=p[t];i!=-1;i=p[e[i].u])
    {
        e[i].f
-=minflow;
        e[i
^1].f+=minflow;
        mincost
+=e[i].w*minflow;
    }
    
return 0;
}
int main()
{
    scanf(
"%d%d",&n,&m);
    
int i;
    
int a,b,c;
    memset(head,
-1,sizeof(head));
    
for(i=1;i<=m;i++)
    {
        scanf(
"%d%d%d",&a,&b,&c);
        addedge(a,b,c,
1);
        addedge(b,a,c,
1);
    }
    s
=0;
    t
=n+1;
    addedge(s,
1,0,2);
    addedge(n,t,
0,2);
    
while(spfa())
    {    
        solve();
    }
    printf(
"%d\n",mincost);
    system(
"pause");
    
return 0;
}