POJ2135

最小费用最大流模板题

题意就是要找两条无交集的从1到n的路线,使距离和最小。

每条路只能走一次。

设置一个源,接到1点,设置一个汇,从n点接到汇。

为保证无交集,我们把每条边的流量设置为1,而源发出的流量和汇接收的流量均为2。每条边的费用就是该边在原图中的权值。

 

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <string.h>
 4 #include <queue>
 5 using namespace std;
 6 const int N=1050;
 7 const int M=10050;
 8 struct{
 9     int v, cap, cost, next, re;//re 逆边的下标
10 }e[M];
11 int n,m,ans,k;
12 int first[N],pre[N],dis[N];
13 void init(){
14     k=0;
15     memset(first,-1,sizeof(first));
16     ans=0;
17 }
18 void addedge(int u,int v,int ca,int co){
19     e[k].v=v;
20     e[k].cap=ca;
21     e[k].cost=co;
22     e[k].next=first[u];
23     e[k].re=k+1;
24     first[u]=k++;
25     e[k].v=u;
26     e[k].cap=0;
27     e[k].cost=-co;
28     e[k].next=first[v];
29     e[k].re=k-1;
30     first[v]=k++;
31 }
32 bool spfa(int s,int t){
33     memset(dis,0x3f,sizeof(dis));
34     queue<int >q;
35     int inq[N]={0};
36     q.push(s);
37     inq[s]=1;
38     dis[0]=0;
39     while(!q.empty()){
40         int u=q.front();
41         q.pop();
42         for(int i=first[u];i!=-1;i=e[i].next){
43             int v=e[i].v;
44             if(e[i].cap&&dis[v]>dis[u]+e[i].cost){
45 
46                 dis[v]=dis[u]+e[i].cost;
47                 pre[v]=i;
48                 if(!inq[v]){
49                     inq[v]=1;
50                     q.push(v);
51                 }
52             }
53         }
54         inq[u]=0;
55     }
56     if(dis[t]==0x3f3f3f3f){return false;}
57     return true;
58 }
59 void solve(){
60     int u, p, sum = 1<<30;
61     for(u = n; u != 0; u = e[e[p].re].v){
62         p = pre[u];
63         sum = min(sum, e[p].cap);
64     }
65     for(u = n; u != 0; u = e[e[p].re].v){
66         p = pre[u];
67         e[p].cap -= sum;
68         e[e[p].re].cap += sum;
69         ans += sum * e[p].cost;
70     }
71 }
72 int main(){
73     int u,v,c;
74     init();
75     scanf("%d%d",&n,&m);
76     while(m--){
77         scanf("%d%d%d",&u,&v,&c);
78         addedge(u,v,1,c);
79         addedge(v,u,1,c);
80     }
81     addedge(0,1,2,0);
82     addedge(n,n+1,2,0);
83 
84     n++;
85     while(spfa(0,n)){solve();}
86     printf("%d\n",ans);
87     return 0;
88 }

 

posted @ 2015-03-20 00:00  Mr.XuJH  阅读(354)  评论(0编辑  收藏  举报