POJ 2135 Farm Tour 最小费用流

来源:互联网 发布:c语言论坛 编辑:程序博客网 时间:2024/05/21 19:41

点击打开链接

题意:n个点,m条边,n<=1e3,m<=1e4 问从1出发到达n,在从n回到1并且每条边经过一次的最短路径?
贪心:从1到n找最短路在把路径反向 在从n到1找最短路,非常容易举出反例(样例即可)该贪心是错误的.

因为边为无向边 所以可以转换成求出两条1~n的路径 并且这两条路径无公共边 路径之和最短
建图:每条边流量为1,费用为长度.上面问题就等价于,求从1~n流量为2的最小费用流 

#include <iostream>#include <algorithm>#include <cstring>#include <queue>#include <cstdio>using namespace std;const int N=2e5+20;const int inf=2e8;int n,m;int head[N],num;struct node{int to,next,vol,cost;}e[4*N];void insert(int u,int v,int vol,int cost){e[num].to=v,e[num].vol=vol,e[num].cost=cost;e[num].next=head[u],head[u]=num++;e[num].to=u,e[num].vol=0,e[num].cost=-cost;//反向边 减少流量,则价格也减少      e[num].next=head[v];      head[v]=num++;  }int inq[N],dist[N],pre[N],path[N];queue<int> q;bool SPFA(int s,int t){while(!q.empty())q.pop();memset(pre,-1,sizeof(pre));memset(dist,0x7f,sizeof(dist));memset(inq,0,sizeof(inq));inq[s]=1,dist[s]=0,q.push(s);while(!q.empty()){int u=q.front();q.pop(),inq[u]=0;for(int i=head[u];i!=-1;i=e[i].next){int v=e[i].to;if(e[i].vol>0&&dist[v]>dist[u]+e[i].cost){dist[v]=dist[u]+e[i].cost;pre[v]=u,path[v]=i;//前一个点和边 if(!inq[v])inq[v]=1,q.push(v);}}}if(pre[t]==-1)return false;return true;}int Min_CostFlow(int s,int t,int F){int cost=0,flow=0;while(SPFA(s,t)){if(flow==F)// break;int f=inf;for(int u=t;u!=s;u=pre[u])f=min(f,e[path[u]].vol);//path[u],u的前一条边 flow+=f,cost+=dist[t]*f;for(int u=t;u!=s;u=pre[u])          {              e[path[u]].vol-=f;              e[path[u]^1].vol+=f;//残余网络           }  }return cost;}int main(){while(cin>>n>>m){int u,v,w;num=0;memset(head,-1,sizeof(head));for(int i=0;i<m;i++){scanf("%d%d%d",&u,&v,&w);insert(u,v,1,w);insert(v,u,1,w);}int ans=Min_CostFlow(1,n,2); cout<<ans<<endl;}return 0;}



原创粉丝点击