题目:http://poj.org/problem?id=2135
题意:来回不走相同路线的最小路径。
分析:增加一个虚拟的start,end,流量为2,费用为0,其他正常的边的流量为1(因为每条边只能走一次),费用为len。建图之后就是一个简单的最小费用流。
题目:http://poj.org/problem?id=2135
题意:来回不走相同路线的最小路径。
分析:增加一个虚拟的start,end,流量为2,费用为0,其他正常的边的流量为1(因为每条边只能走一次),费用为len。建图之后就是一个简单的最小费用流。
const int inf_int(1e9);
const int maxn(5+1000);
struct EEEE
{
int en,next;
int flow,cost;
}E[2*1000000];
int T,p[maxn];
inline void addEDGE(int st,int en,int flow,int cost)
{
E[T].en=en, E[T].next=p[st], E[T].flow=flow, E[T].cost=cost, p[st]=T++;
swap(st,en), flow=0, cost= -cost;
E[T].en=en, E[T].next=p[st], E[T].flow=flow, E[T].cost=cost, p[st]=T++;
}
int start,end;
int dis[maxn],preedge[maxn];
bool inque[maxn];
queueque;
bool spfa_mincost(int n)
{
int e,a,b;
for(e=0; e <= n; e++)
{
inque[e] = false;
dis[e] = (e==start ? 0:inf_int);
}
preedge[start] = -1;
while(!que.empty())
que.pop();
que.push(start);
while(!que.empty())
{
a=que.front(), que.pop(), inque[a]=false;
for(e=p[a]; e+1; e=E[e].next)
{
b = E[e].en;
if(E[e].flow && dis[b] > dis[a]+E[e].cost)
{
dis[b] = dis[a]+E[e].cost;
preedge[b] = e;
if(!inque[b])
{
inque[b] = true;
que.push(b);
}
}
}
}
return dis[end] != inf_int;
}
void mcmf(int n)
{
int e,aug,maxflow=0,mincost=0;
while(spfa_mincost(n))
{
aug = inf_int;
for(e=preedge[end]; e+1; e=preedge[E[e^1].en])
aug = min(aug, E[e].flow);
for(e=preedge[end]; e+1; e=preedge[E[e^1].en])
{
E[e].flow -= aug;
E[e^1].flow += aug;
}
maxflow += aug;
mincost += aug*dis[end];
}
//printf("maxflow:%d mincost:%d\n", maxflow,mincost);
printf("%d\n", mincost);
}
int main()
{
int n,m;
int a,b,len;
while(cin>>n>>m)
{
T=0, memset(p, -1, sizeof p);
start=0, end=n+1;
addEDGE(start, 1, 2, 0);
addEDGE(n, end, 2, 0);
while(m--)
{
scanf("%d %d %d", &a,&b,&len);
addEDGE(a,b,1,len);
addEDGE(b,a,1,len);
}
mcmf(n+2);
}
return 0;
}