hdu4411 Arrest(费用流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4411

【题意】给定N+1个点,距离,K个人,问,每人从0开始按照升序访问节点然后回到0,每个节点被访问一次的最小距离和。

【分析】费用流问题,因为每个点只能被访问一次,所以拆点iX,iY,容量为1,Floyd后建图,因为每个点都必须被访问,所以费用设为-M,这样找最小费用的时候一定会选取iX-iY。另外加源点到汇点的边(s,t,k,0),防止负权回路。这是一类好题啊。

 

ZKW_flow 109 ms:

  1 #include<functional>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<vector>
  8 #include<queue>
  9 #define REP(i, n) for(int i=0; i<n; i++)
 10 #define FF(i, a, b) for(int i=a; i<b; i++)
 11 #define CLR(a, b) memset(a, b, sizeof(a))
 12 #define PB push_back
 13 using namespace std;
 14 
 15 const int MAXN = 455;
 16 const int MAXE = MAXN*MAXN/2;
 17 const int INF = 1e8;
 18 struct ZKW_flow
 19 {
 20     int st, ed, ecnt, n;
 21     int head[MAXN];
 22     int cap[MAXE], cost[MAXE], to[MAXE], next[MAXE], dis[MAXN]; ;
 23 
 24     void init()
 25     {
 26         memset(head, 0, sizeof(head));
 27         ecnt = 2;
 28     }
 29 
 30     void AddEdge(int u, int v, int cc, int ww)
 31     {
 32         cap[ecnt] = cc;
 33         cost[ecnt] = ww;
 34         to[ecnt] = v;
 35         next[ecnt] = head[u];
 36         head[u] = ecnt++;
 37         cap[ecnt] = 0;
 38         cost[ecnt] = -ww;
 39         to[ecnt] = u;
 40         next[ecnt] = head[v];
 41         head[v] = ecnt++;
 42     }
 43 
 44     void SPFA()
 45     {
 46         REP(i, n+1) dis[i] = INF;
 47         priority_queue<pair<int, int> > Q;
 48         dis[st] = 0;
 49         Q.push(make_pair(0, st));
 50         while(!Q.empty())
 51         {
 52             int u = Q.top().second, d = -Q.top().first;
 53             Q.pop();
 54             if(dis[u] != d) continue;
 55             for(int p = head[u]; p; p = next[p])
 56             {
 57                 int &v = to[p];
 58                 if(cap[p] && dis[v] > d + cost[p])
 59                 {
 60                     dis[v] = d + cost[p];
 61                     Q.push(make_pair(-dis[v], v));
 62                 }
 63             }
 64         }
 65         REP(i, n+1) dis[i] = dis[ed] - dis[i];
 66     }
 67 
 68     int minCost, maxFlow;
 69     bool use[MAXN];
 70 
 71     int add_flow(int u, int flow)
 72     {
 73         if(u == ed)
 74         {
 75             maxFlow += flow;
 76             minCost += dis[st] * flow;
 77             return flow;
 78         }
 79         use[u] = true;
 80         int now = flow;
 81         for(int p = head[u]; p; p = next[p])
 82         {
 83             int &v = to[p];
 84             if(cap[p] && !use[v] && dis[u] == dis[v] + cost[p])
 85             {
 86                 int tmp = add_flow(v, min(now, cap[p]));
 87                 cap[p] -= tmp;
 88                 cap[p^1] += tmp;
 89                 now -= tmp;
 90                 if(!now) break;
 91             }
 92         }
 93         return flow - now;
 94     }
 95 
 96     bool modify_label()
 97     {
 98         int d = INF;
 99         REP(u, n+1) if(use[u])
100             for(int p = head[u]; p; p = next[p])
101             {
102                 int &v = to[p];
103                 if(cap[p] && !use[v]) d = min(d, dis[v] + cost[p] - dis[u]);
104             }
105         if(d == INF) return false;
106         REP(i, n+1) if(use[i]) dis[i] += d;
107         return true;
108     }
109 
110     int Mincost(int ss, int tt, int nn)
111     {
112         st = ss, ed = tt, n = nn;
113         minCost = maxFlow = 0;
114         SPFA();
115         while(true)
116         {
117             while(true)
118             {
119                 CLR(use, 0);
120                 if(!add_flow(st, INF)) break;
121             }
122             if(!modify_label()) break;
123         }
124         return minCost;
125     }
126 } MC;
127 
128 const int maxn = 111;
129 int n, m, k;
130 
131 int mp[maxn][maxn];
132 
133 
134 void solve()
135 {
136     int nn = 2*n + 3;
137     int s = 0, ss = 2*n + 1, t = ss + 1;
138     MC.init();
139     MC.AddEdge(s, ss, k,0);
140     MC.AddEdge(ss,t,k,0);
141     int tmp = 1e7;
142     for (int i=1;i<=n;i++)
143     {
144         MC.AddEdge(ss, i, 1, mp[0][i]);
145         MC.AddEdge(i, i+n, 1, -tmp);
146         MC.AddEdge(i+n, t,1,mp[0][i]);
147         for (int j=i+1;j<=n;j++)
148         {
149             MC.AddEdge(i+n, j, 1, mp[i][j]);
150         }
151     }
152     printf("%d\n",MC.Mincost(s,t,nn) + n * tmp);
153     return ;
154 }
155 int main()
156 {
157     while (scanf("%d%d%d",&n,&m,&k)==3)
158     {
159         if (n == 0)
160             break;
161         for (int i=0;i<=n;i++)
162         {
163             for (int j=0;j<=n;j++){
164                 mp[i][j] = INF;
165             }
166         }
167         while (m--)
168         {
169             int x, y, z;
170             scanf("%d%d%d",&x,&y,&z);
171             mp[x][y] = min(mp[x][y],z);
172             mp[y][x] = min(mp[y][x],z);
173         }
174 
175         for (int k=0;k<=n;k++)
176             for (int i=0;i<=n;i++)
177                 for (int j=0;j<=n;j++)
178                 {
179                     mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
180                 }
181 
182         solve();
183     }
184     return 0;
185 }
hdu4411

 

另外一个费用流模板 62ms:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define maxn 1010
  9 #define maxm 20010
 10 const int inf = 0x3f3f3f3f;
 11 
 12 struct Nod {
 13     int b, nxt;
 14     int cap, cst;
 15     void init(int b, int nxt, int cap, int cst) {
 16         this->b = b;
 17         this->nxt = nxt;
 18         this->cap = cap;
 19         this->cst = cst;
 20     }
 21 };
 22 struct MinCost {
 23     int E[maxn];
 24     int n;
 25     Nod buf[maxm * 2];
 26     int len;
 27     int p[maxn];
 28     void init(int n) {
 29         this->n = n;
 30         memset(E, 255, sizeof(E));
 31         len = 0;
 32     }
 33     void AddEdge(int a, int b, int cap, int cst) {
 34         buf[len].init(b, E[a], cap, cst);
 35         E[a] = len++;
 36         buf[len].init(a, E[b], 0, -cst);
 37         E[b] = len++;
 38     }
 39     bool spfa(int source, int sink) {
 40         static queue<int> q;
 41         static int d[maxn];
 42         memset(d, 63, sizeof(d));
 43         memset(p, 255, sizeof(p));
 44         d[source] = 0;
 45         q.push(source);
 46         int u, v;
 47         while (!q.empty()) {
 48             u = q.front();
 49             q.pop();
 50             for (int i = E[u]; i != -1; i = buf[i].nxt) {
 51                 v = buf[i].b;
 52                 if (buf[i].cap > 0 && d[u] + buf[i].cst < d[v]) {
 53                     d[v] = d[u] + buf[i].cst;
 54                     p[v] = i;
 55                     q.push(v);
 56                 }
 57             }
 58         }
 59         return d[sink] != inf;
 60     }
 61     int Mincost(int source, int sink) {
 62         int minCost = 0, maxFlow = 0;//需要maxFlow的话,想办法返回
 63         while (spfa(source, sink)) {
 64             int neck = inf;
 65             for (int t = p[sink]; t != -1; t = p[buf[t ^ 1].b])//buf[t^壹].b是父节点
 66                 neck = min(neck, buf[t].cap);
 67             maxFlow += neck;
 68             for (int t = p[sink]; t != -1; t = p[buf[t ^ 1].b]) {
 69                 buf[t].cap -= neck;
 70                 buf[t ^ 1].cap += neck;
 71                 minCost += buf[t].cst * neck;
 72             }
 73         }
 74         return minCost;
 75     }
 76 } MC;
 77 
 78 int n, m, k;
 79 
 80 int mp[maxn][maxn];
 81 
 82 
 83 void solve()
 84 {
 85     int nn = 2*n + 3;
 86     int s = 0, ss = 2*n + 1, t = ss + 1;
 87     MC.init(nn);
 88     MC.AddEdge(s, ss, k,0);
 89     MC.AddEdge(ss,t,k,0);
 90     int tmp = 1e7;
 91     for (int i=1;i<=n;i++)
 92     {
 93         MC.AddEdge(ss, i, 1, mp[0][i]);
 94         MC.AddEdge(i, i+n, 1, -tmp);
 95         MC.AddEdge(i+n, t,1,mp[0][i]);
 96         for (int j=i+1;j<=n;j++)
 97         {
 98             MC.AddEdge(i+n, j, 1, mp[i][j]);
 99         }
100     }
101     printf("%d\n",MC.Mincost(s,t) + n * tmp);
102     return ;
103 }
104 int main()
105 {
106     while (scanf("%d%d%d",&n,&m,&k)==3)
107     {
108         if (n == 0)
109             break;
110         for (int i=0;i<=n;i++)
111         {
112             for (int j=0;j<=n;j++){
113                 mp[i][j] = inf;
114             }
115         }
116         while (m--)
117         {
118             int x, y, z;
119             scanf("%d%d%d",&x,&y,&z);
120             mp[x][y] = min(mp[x][y],z);
121             mp[y][x] = min(mp[y][x],z);
122         }
123 
124         for (int k=0;k<=n;k++)
125             for (int i=0;i<=n;i++)
126                 for (int j=0;j<=n;j++)
127                 {
128                     mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
129                 }
130 
131         solve();
132     }
133     return 0;
134 }
hdu4411

 

转载于:https://www.cnblogs.com/wangsouc/articles/3711202.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值