poj 2135 Farm Tour

题意:求从顶点1走到n再走回1的最短路径,每条边只能走一次。

解法:最小费用最大流,另设源点汇点,从源点到1连边,从n到汇点连边,这两条边都是容量为2,费用为0,表示要走两条包含源点(或汇点)的边,因为一去一回走的边不一样。。其余的边正常建就行,费用就是路径长度。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 #define N 1010
 6 using namespace std;
 7 const int inf=1<<30;
 8 struct Edge{
 9     int u,v,c,len,next;
10     Edge(){}
11     Edge(int _u,int _v,int _c,int _len,int _next){
12         u=_u;v=_v;c=_c;len=_len;next=_next;
13     }
14 }edge[N*N];
15 int head[N],pre[N],cnt;
16 int dis[N];
17 bool vis[N];
18 int source,sink,n,m;
19 void init(){
20     memset(head,-1,sizeof(head));
21     cnt=0;
22 }
23 void addedge(int u,int v,int c,int len){
24     edge[cnt]=Edge(u,v,c,len,head[u]);
25     head[u]=cnt++;
26 }
27 bool spfa(int st,int ed){
28     memset(vis,0,sizeof(vis));
29     memset(pre,-1,sizeof(pre));
30     queue<int>Q;
31     for(int i=0;i<=n+1;i++)dis[i]=inf;
32     Q.push(st);dis[st]=0;
33     vis[st]=1;
34     while(!Q.empty()){
35         int p=Q.front();Q.pop();
36         vis[p]=0;
37         for(int k=head[p];k!=-1;k=edge[k].next){
38             int v=edge[k].v,len=edge[k].len,c=edge[k].c;
39             if(c>0&&dis[v]>dis[p]+len){
40                 dis[v]=dis[p]+len;
41                 pre[v]=k;
42                 if(!vis[v]){
43                     Q.push(v);
44                     vis[v]=1;
45                 }
46             }
47         }
48     }
49     if(dis[ed]==inf)return 0;
50     return 1;
51 }
52 int solve(){
53     int ans=0;
54     while(spfa(source,sink)){
55         int minn=inf;
56         for(int k=pre[sink];k!=-1;k=pre[edge[k].u])
57             minn=min(minn,edge[k].c);
58         for(int k=pre[sink];k!=-1;k=pre[edge[k].u]){
59             edge[k].c-=minn;
60             edge[k^1].c+=minn;
61         }
62         ans+=minn*dis[sink];
63     }
64     return ans;
65 }
66 int main(){
67     while(~scanf("%d%d",&n,&m)){
68         init();
69         source=0;
70         sink=n+1;
71         for(int i=1;i<=m;i++){
72             int u,v,w;
73             scanf("%d%d%d",&u,&v,&w);
74             addedge(u,v,1,w);
75             addedge(v,u,0,-w);
76             addedge(v,u,1,w);
77             addedge(u,v,0,-w);
78         }
79         addedge(source,1,2,0);
80         addedge(1,source,0,0);
81         addedge(n,sink,2,0);
82         addedge(sink,n,0,0);
83         int ans=solve();
84         printf("%d\n",ans);
85     }
86     return 0;
87 }

 

posted @ 2013-01-20 16:16  silver__bullet  阅读(193)  评论(0编辑  收藏  举报