poj 2135 Farm Tour 费用流

来源:互联网 发布:红警共和国之辉mac 编辑:程序博客网 时间:2024/06/06 07:32

题意:给出一个无向图,问从起点到终点再回到起点的一条最短路是多少,且每条边只能用一次。


分析:将问题转换成从起点找两条到终点的最短的不同路径。

设立源点和汇点,从源点到起点和终点到汇点之间连一条容量为2费用为0的边。

每一条边看成是容量为1费用为w的边。

然后跑一遍费用流就是答案了。


代码:

#include<iostream>#include<cstdio>#include<cstdlib>#define inf 0x7fffffffusing namespace std;int n,m,s,t,cnt,last[2005],ans,dis[2001],v[2001],q[2001],pre[2001];struct data{int x,y,c,w,op,next;}e[300001];void insert(int x,int y,int c,int w){cnt++;e[cnt].x=x;e[cnt].y=y;e[cnt].c=c;e[cnt].w=w;e[cnt].op=cnt+1;e[cnt].next=last[x];last[x]=cnt;cnt++;e[cnt].x=y;e[cnt].y=x;e[cnt].c=0;e[cnt].w=-w;e[cnt].op=cnt-1;e[cnt].next=last[y];last[y]=cnt;}bool spfa(){for (int i=s;i<=t;i++){dis[i]=inf;v[i]=0;}dis[s]=0;v[s]=1;int head=0,tail=1;q[1]=s;while (head!=tail){if (head==2000) head=0;head++;int now=q[head],i=last[now];while(i){if (e[i].c&&dis[now]+e[i].w<dis[e[i].y]){dis[e[i].y]=dis[now]+e[i].w;pre[e[i].y]=i;if (!v[e[i].y]){v[e[i].y]=1;if (tail==2000) tail=0;tail++;q[tail]=e[i].y;}}i=e[i].next;}v[now]=0;}if (dis[t]==inf) return 0;return 1;}void mcf(){int x=inf,i=t;while (pre[i]){x=min(x,e[pre[i]].c);i=e[pre[i]].x;}i=t;while (pre[i]){e[pre[i]].c-=x;e[e[pre[i]].op].c+=x;ans+=x*e[pre[i]].w;i=e[pre[i]].x;}}int main(){scanf("%d%d",&n,&m);s=0;t=n+1;for (int i=1;i<=m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);insert(u,v,1,w);insert(v,u,1,w);}insert(s,1,2,0);insert(n,t,2,0);while (spfa()) mcf();printf("%d\n",ans);return 0;}


0 0
原创粉丝点击