hdu4494(Teamwork)-2013通化邀请赛B题-费用流

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

 

【题意】有N个城市(坐标Xi,Yi)需要修复,m种兵种,修复有开始时间和完成时间,对每种兵种有人数要求。初始兵种都在X0,Y0位置。两个城市之间转移士兵需要的时间是欧几里得距离。求休整完所有城市,最少需要多少士兵。

【分析】

1、对于每个兵种相互独立没有影响,因此,对于每种兵种求出最小值求和。

2、对于每个任务建图,有两种做法,一种是跑费用流;一种是跑可行流判定。

费用流:每个点拆为3个点,x,y,z,(s,x,inf,0),(x,y,t,need,0),(x,y,need,0),(s,z,need,0);对于i != k如果ed[i] + dis(i,j) <= st[j],(iz,ky,ineed,0);求最小费用即可。

这里添加点z,表示,i点的流量ineed可以跑到k点,继续使用,费用为0。

这个模板很好用。

  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 = 1e9;
 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 } Flow;
127 
128 int n, m;
129 
130 struct Point{
131     double x, y;
132     double st, ed;
133     int v[11];
134 
135 }sq[111];
136 
137 double dist(Point p, Point q)
138 {
139     return sqrt((p.x - q.x)*(p.x - q.x) + (p.y - q.y)*(p.y - q.y));
140 }
141 
142 void solve()
143 {
144     int s = 0, t = 3*n + 1;
145     int res = 0;
146     for (int j=0;j<m;j++)
147     {
148         Flow.init();
149         for (int i=1;i<n;i++)
150         {
151             Flow.AddEdge(s, i,INF, 1);
152             Flow.AddEdge(i,i+2*n,sq[i].v[j],0);
153             Flow.AddEdge(i+2*n, t, sq[i].v[j],0);
154             Flow.AddEdge(s, i+n, sq[i].v[j], 0);
155         }
156         for (int i=1;i<n;i++)
157         {
158             for (int k=1;k<n;k++)
159             {
160                 if (i != k)
161                 {
162                     if (sq[i].ed + dist(sq[i], sq[k]) <= sq[k].st)
163                     {
164                         Flow.AddEdge(i+n, k+2*n,sq[i].v[j],0);
165                     }
166                 }
167             }
168         }
169         res += Flow.Mincost(s,t,t);
170     }
171     printf("%d\n",res);
172     return ;
173 }
174 int main()
175 {
176     int cas;
177     scanf("%d", &cas);
178     while (cas--)
179     {
180         scanf("%d%d",&n,&m);
181         scanf("%lf%lf",&sq[0].x, &sq[0].y);
182         for (int i=1;i<n;i++)
183         {
184             scanf("%lf%lf%lf%lf",&sq[i].x, &sq[i].y, &sq[i].st, &sq[i].ed);
185             sq[i].ed += sq[i].st;
186 
187             for (int j=0;j<m;j++)
188             {
189                 scanf("%d",&sq[i].v[j]);
190             }
191         }
192 
193         solve();
194     }
195     return 0;
196 }
hdu4494

 

 

 

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值