• HDU 4289:Control(最小割)


    http://acm.hdu.edu.cn/showproblem.php?pid=4289

    题意:有n个城市,m条无向边,小偷要从s点开始逃到d点,在每个城市安放监控的花费是sa[i],问最小花费可以监控到所有小偷。

    思路:求最小割可以转化为最大流。每个城市之间拆点,流量是sa[i],再增加一个超级源点S和s相连,增加一个超级汇点T,让d的第二个点和T相连。然后就可以做了。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 using namespace std;
     12 #define INF 0x3f3f3f3f
     13 #define N 100010
     14 #define M 510
     15 typedef long long LL;
     16 struct Edge {
     17     int v, nxt, cap;
     18     Edge () {}
     19     Edge (int v, int cap, int nxt) : v(v), cap(cap), nxt(nxt) {}
     20 }edge[N*10];
     21 int head[M], tot, gap[M], dis[M], cur[M], pre[M];
     22 int sa[M], S, T;
     23 
     24 void Add(int u, int v, int cap) {
     25     edge[tot] = Edge(v, cap, head[u]); head[u] = tot++;
     26     edge[tot] = Edge(u, 0, head[v]); head[v] = tot++;
     27 }
     28 
     29 void BFS() {
     30     memset(dis, -1, sizeof(dis));
     31     memset(gap, 0, sizeof(gap));
     32     queue<int> que; que.push(T);
     33     dis[T] = 0; gap[0]++;
     34     while(!que.empty()) {
     35         int u = que.front(); que.pop();
     36         for(int i = head[u]; ~i; i = edge[i].nxt) {
     37             Edge& e = edge[i];
     38             if(~dis[e.v]) continue;
     39             dis[e.v] = dis[u] + 1;
     40             gap[dis[e.v]]++;
     41             que.push(e.v);
     42         }
     43     }
     44 }
     45 
     46 int ISAP(int n) {
     47     BFS(); // 别忘了调用!
     48     memcpy(cur, head, sizeof(cur));
     49     int u = pre[S] = S, ans = 0, i;
     50     while(dis[S] < n) {
     51         if(u == T) {
     52             int flow = INF, index;
     53             for(i = S; i != T; i = edge[cur[i]].v)
     54                 if(flow > edge[cur[i]].cap)
     55                     flow = edge[cur[i]].cap, index = i;
     56             for(i = S; i != T; i = edge[cur[i]].v)
     57                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
     58             u = index; ans += flow;
     59         }
     60         for(i = cur[u]; ~i; i = edge[i].nxt)
     61             if(dis[edge[i].v] == dis[u] - 1 && edge[i].cap > 0) break;
     62         if(~i) {
     63             pre[edge[i].v] = u; cur[u] = i;
     64             u = edge[i].v;
     65         } else {
     66             if(--gap[dis[u]] == 0) break;
     67             int md = n;
     68             for(i = head[u]; ~i; i = edge[i].nxt)
     69                 if(edge[i].cap > 0 && dis[edge[i].v] < md)
     70                     md = dis[edge[i].v], cur[u] = i;
     71             ++gap[dis[u] = md + 1];
     72             u = pre[u];
     73         }
     74     }
     75     return ans;
     76 }
     77 
     78 int main() {
     79     int n, m;
     80     while(~scanf("%d%d", &n, &m)) {
     81         int s, t;
     82         scanf("%d%d", &s, &t);
     83         memset(head, -1, sizeof(head)); tot = 0;
     84         S = 0, T = 2 * n + 1;
     85         // 第一个点是1~n,第二个点是n+1~2*n,第一个点为进来的点,第二个点为出去的点
     86         Add(S, s, INF); Add(t + n, T, INF);
     87         for(int i = 1; i <= n; i++) scanf("%d", &sa[i]);
     88         for(int i = 1; i <= m; i++) {
     89             int u, v;
     90             scanf("%d%d", &u, &v);
     91             Add(u + n, v, INF);
     92             Add(v + n, u, INF);
     93         }
     94         for(int i = 1; i <= n; i++)
     95             Add(i, i + n, sa[i]);
     96         int ans = ISAP(T + 1);
     97         printf("%d
    ", ans);
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    第二阶段冲刺第一天
    第一次团队绩效评估
    其他团队对本团队评价的总结
    对其他团队的评价
    团队博客的检查结果
    站立会议第十天
    站立会议第九天
    站立会议第八天
    站立会议第七天
    团队站立会议10
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6240723.html
Copyright © 2020-2023  润新知