csu 1506 Double Shortest Paths 最小费用最大流

题意:

两个人从1走到n

每条边走第一次花费是w1 第二次是w1+w2

问最少费用

思路:

印象中能纠正的就是最小费用最大流 就试着用了一下

每条遍分解成第一次走和第二次走两种情况

然后手动添加源点汇点 直接跑一遍模板就行了

(感谢kuangbin~

注意边都加了两遍 所以边的集合要开两倍

  1 #include<bits/stdc++.h>
  2 #define cl(a,b) memset(a,b,sizeof(a))
  3 #define debug(x) cerr<<#x<<"=="<<(x)<<endl
  4 using namespace std;
  5 
  6 const int maxn = 500+10;
  7 const int maxm = 4000+10;
  8 const int inf = 0x3f3f3f3f;
  9 
 10 struct Edge
 11 {
 12     int to, next, cap, flow, cost;
 13 }edge[maxm];
 14 
 15 int n,m;
 16 int head[maxn],tol;
 17 int pre[maxn],dis[maxn];
 18 bool vis[maxn];
 19 
 20 void init()
 21 {
 22     tol = 0;
 23     cl(head,-1);
 24 }
 25 
 26 void addedge(int u, int v, int cap, int cost)
 27 {
 28     edge[tol].to=v;
 29     edge[tol].cap=cap;
 30     edge[tol].cost=cost;
 31     edge[tol].flow=0;
 32     edge[tol].next=head[u];
 33     head[u]=tol++;
 34     edge[tol].to=u;
 35     edge[tol].cap=0;
 36     edge[tol].cost=-cost;
 37     edge[tol].flow=0;
 38     edge[tol].next=head[v];
 39     head[v]=tol++;
 40 }
 41 
 42 bool spfa(int s, int t)
 43 {
 44     queue<int>q;
 45     while(!q.empty()) q.pop();
 46     cl(dis,inf),cl(vis,false),cl(pre,-1);
 47     dis[s] = 0;
 48     vis[s] = true;
 49     q.push(s);
 50     while(!q.empty())
 51     {
 52         int u = q.front();
 53         q.pop();
 54         vis[u] = false;
 55         for(int i = head[u]; i != -1; i = edge[i]. next)
 56         {
 57             int v = edge[i]. to;
 58             if(edge[i]. cap > edge[i]. flow &&
 59                dis[v] > dis[u] + edge[i]. cost )
 60             {
 61                 dis[v] = dis[u] + edge[i]. cost;
 62                 pre[v] = i;
 63                 if(!vis[v])
 64                 {
 65                     vis[v] = true;
 66                     q.push(v);
 67                 }
 68             }
 69         }
 70     }
 71     if(pre[t] == -1) return false;
 72     else return true;
 73 }
 74 
 75 void solve(int s, int t, int &cost)
 76 {
 77     int flow = 0;
 78     cost = 0;
 79     while(spfa(s,t))
 80     {
 81         int Min = inf;
 82         for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
 83         {
 84             if(Min > edge[i]. cap - edge[i]. flow)
 85                 Min = edge[i]. cap - edge[i]. flow;
 86         }
 87         for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
 88         {
 89             edge[i]. flow += Min;
 90             edge[i^1]. flow -= Min;
 91             cost += edge[i]. cost * Min;
 92         }
 93         flow += Min;
 94     }
 95 }
 96 
 97 int main()
 98 {
 99     int u,v,w1,w2;
100     int cas = 0;
101     while(~scanf("%d%d",&n,&m))
102     {
103         init();
104         for(int i = 0; i < m; i++)
105         {
106             scanf("%d%d%d%d",&u,&v,&w1,&w2);
107             //每一条边分解成两条流量是1的边
108             //一条费用是w1
109             addedge(u,v,1,w1);
110             //另外一条是w1+w2
111             addedge(u,v,1,w1+w2);
112         }
113         //手动加入源点汇点 流量都是2
114         addedge(0,1,2,0);
115         addedge(n,n+1,2,0);
116         int ans=0;
117         solve(0,n+1,ans);
118         printf("Case %d: %d
",++cas,ans);
119     }
120     return 0;
121 }/*
122 
123 4 4
124 1 2 5 1
125 2 4 6 0
126 1 3 4 0
127 3 4 9 1
128 4 4
129 1 2 5 10
130 2 4 6 10
131 1 3 4 10
132 3 4 9 10
133 
134 */
原文地址:https://www.cnblogs.com/general10/p/6817088.html