HLPP算法 一种高效的网络最大流算法

 1 #include <algorithm>
 2 #include <cstdio>
 3 #include <cctype>
 4 #include <queue>
 5 #define INF 0x3f3f3f3f
 6 #define MAXN 10010
 7 #define MAXM 300010
 8 using namespace std;
 9 int n, m, s, t, tot = 1;
10 int beginx[MAXN], endx[MAXM], nxt[MAXM], res[MAXM];
11 inline void add_edge(int u, int v, int w)
12 {
13     nxt[++tot] = beginx[u], beginx[u] = tot, endx[tot] = v, res[tot] = w;
14     nxt[++tot] = beginx[v], beginx[v] = tot, endx[tot] = u, res[tot] = 0;
15 }
16 struct PQ
17 {
18     int x,h;
19     PQ(int _x,int _h)
20     {
21         x = _x, h = _h;
22     }
23     bool operator <  (const PQ &tar) const
24     {
25         return h < tar.h;
26     }
27 };
28 int gap[MAXN], d[MAXN], ans[MAXN];
29 inline bool push(int x, int y, int ptr)
30 {
31     int w = min(ans[x], res[ptr]);
32     res[ptr] -= w, res[ptr^1] += w;
33     ans[x] -= w, ans[y] += w;
34     return w;
35 }
36 inline void Gap(int val)
37 {
38     for (int i = 1; i <= n; ++i)
39         if(i != s && i != t && val < d[i] && d[i] <= n)
40             d[i] = n + 1;
41 }
42 inline int HLPP()
43 {
44     priority_queue<PQ> pq;
45     d[s] = n, ans[s] = INF, pq.push(PQ(s, d[s]));
46     int u;
47     while(!pq.empty())
48     {
49         u = pq.top().x, pq.pop();
50         if(!ans[u]) continue;
51         for(int i = beginx[u], v = endx[i]; i; i = nxt[i], v = endx[i])
52             if((u == s || d[u] == d[v] + 1) && push(u, v, i) && v != t && v != s)
53                 pq.push(PQ(v, d[v]));
54         if (u != s && u != t && ans[u]) 
55         {
56             if(!(--gap[d[u]])) Gap(d[u]);
57             ++gap[++d[u]];
58             pq.push(PQ(u, d[u]));
59         }
60     }
61     return ans[t];
62 }
63 int main()
64 {
65     scanf("%d%d%d%d",&n,&m,&s,&t);
66     for(int i = 1; i <= m; i++)
67     {
68         int u,v,r;
69         scanf("%d%d%d",&u,&v,&r);
70         add_edge(u, v, r);
71     }
72     printf("%d", HLPP());
73     return 0;
74 }
HLPP

主程序仅有35行,可能会TLE,需要卡卡常数。

暴露出的问题:

- priority_queue太慢,用pq比普通队列还慢。

- STL效率差到爆炸,明明是需要多次BFS,入队出队次数很多,然而效率低,没办法,卡死了。

  1 #include <cstdio>
  2 #include <cctype>
  3 using namespace std;
  4 #define MAXN 10005
  5 #define MAXM 200010
  6 #define INF 0x3f3f3f3f
  7 
  8 inline char get_char()
  9 {
 10     static char buf[1000001], *p1 = buf, *p2 = buf;
 11     return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1 ++;
 12 }
 13 inline int read()
 14 {
 15     register int num = 0;
 16     char c;
 17     while (isspace(c = get_char()));
 18     while (num = num * 10 + c - 48, isdigit(c = get_char()));
 19     return num;
 20 }
 21 inline void upmin(int &a, const int &b)
 22 {
 23     if(a > b) a = b;
 24 }
 25 
 26 int beginx[MAXN], endx[MAXM], nxt[MAXM], res[MAXM];
 27 
 28 struct Q
 29 {
 30     int s, t;
 31     Q()
 32     {
 33         s = 1 , t = 0;
 34     }
 35     int q[MAXM];
 36     inline bool empty()
 37     {
 38         return s > t;
 39     }
 40     inline int front()
 41     {
 42         return q[s++];
 43     }
 44     inline void push(int tar)
 45     {
 46         q[++t] = tar;
 47     }
 48 } mession;
 49 
 50 int main()
 51 {
 52     register int n = read(), m = read(), s = read(), t = read(), tot = 1;
 53     for(int i = 1; i <= m; i++)
 54     {
 55         int u = read(), v = read(), c = read();
 56         nxt[++tot] = beginx[u], beginx[u] = tot, endx[tot] = v, res[tot] = c;
 57         nxt[++tot] = beginx[v], beginx[v] = tot, endx[tot] = u, res[tot] = 0;
 58     }
 59     register int ar = s, r = INF, ans = 0;
 60     bool done;
 61     int d[MAXN], num[MAXN], cur[MAXN], pre[MAXN];
 62     mession.push(t);
 63     d[t] = 1;
 64     register int u, v;
 65     while(!mession.empty())
 66     {
 67         u = mession.front();
 68         num[d[u]]++;
 69         for(int i = beginx[u]; i; i = nxt[i])
 70         {
 71             v = endx[i];
 72             if(!d[v] && res[i ^ 1])
 73             {
 74                 d[v] = d[u] + 1;
 75                 mession.push(v);
 76             }
 77         }
 78     }
 79     for(int i = 1; i <= n; i++) cur[i] = beginx[i];
 80     while(d[s] != n + 1)
 81     {
 82         if(ar == t)
 83         {
 84             while(ar != s)
 85             {
 86                 res[pre[ar]] -= r, res[pre[ar] ^ 1] += r;
 87                 ar = endx[pre[ar] ^ 1];
 88             }
 89             ans += r, r = INF;
 90         }
 91         done = false;
 92         for(int &i = cur[ar]; i; i = nxt[i])
 93         {
 94             int v = endx[i];
 95             if(res[i] && d[v] == d[ar] - 1)
 96             {
 97                 done = true, pre[v] = i, ar = v;
 98                 upmin(r, res[i]);
 99                 break;
100             }
101         }
102         if(!done)
103         {
104             register int heig = n + 1;
105             for(int i = beginx[ar]; i; i = nxt[i])
106             {
107                 int v = endx[i];
108                 if(res[i]) upmin(heig, d[v] + 1);
109             }
110             if(--num[d[ar]] == 0) break;
111             cur[ar] = beginx[ar];
112             num[d[ar] = heig]++;
113             if(ar != s) ar = endx[pre[ar] ^ 1];
114         }
115     }
116     printf("%d", ans);
117     return 0;
118 }

 

posted @ 2017-12-14 21:06  baka  阅读(692)  评论(0编辑  收藏  举报