题意:
n 个排成一列的哨站要进行通信。第 i 个哨站的频段为 ai。
每个哨站 ii 需要选择以下二者之一:
1.直接连接到控制中心,代价为 W;
2.连接到前面的某个哨站 j(j<i),代价为 |ai−aj|。 每个哨站只能被后面的至多一个哨站连接。
请你求出最小可能的代价和。
题解:
显然的费用流
然后我耿直的n^2建边,觉得我的费用流很快,应该可以过
然后返回了TLE
然后google了一下题解:发现这题卡了n^2建图,需要优化建边
我这里是通过分治优化的
就是类似与建立一个虚点
一个x要向y的一个前缀建图,所以就可以类似前缀和优化建图那样,
按权值排序然后建出一条链,链上两个点之间的流量为INF,费用为权值之差,然后每个点向对应的点连边
但这样建图是错误的,原因在于我们把点排了序,改变了编号顺序,
所以一个点能到达的点不一定是它可以到达的
所以我们要固定在固定编号顺序的情况下这样连边,也就是说x的一个区间和y的一个区间之间这样连边,
要求两个区间不重合,且x的区间比y的区间小
那么很容易想到分治建图,每次让[l,mid]向[mid+1,r]连边,剩下的递归下去就行了
1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 #include <unordered_map> 14 15 #define pi acos(-1.0) 16 #define eps 1e-9 17 #define fi first 18 #define se second 19 #define rtl rt << 1 20 #define rtr rt << 1 | 1 21 #define bug printf("****** ") 22 #define mem(a, b) memset(a, b, sizeof(a)) 23 #define name2str(x) #x 24 #define fuck(x) cout << #x " = " << x << endl 25 #define sfi(a) scanf("%d", &a) 26 #define sffi(a, b) scanf("%d %d", &a, &b) 27 #define sfffi(a, b, c) scanf("%d %d %d", &a, &b, &c) 28 #define sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d) 29 #define sfL(a) scanf("%lld", &a) 30 #define sffL(a, b) scanf("%lld %lld", &a, &b) 31 #define sfffL(a, b, c) scanf("%lld %lld %lld", &a, &b, &c) 32 #define sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d) 33 #define sfs(a) scanf("%s", a) 34 #define sffs(a, b) scanf("%s %s", a, b) 35 #define sfffs(a, b, c) scanf("%s %s %s", a, b, c) 36 #define sffffs(a, b, c, d) scanf("%s %s %s %s", a, b, c, d) 37 #define FIN freopen("../in.txt", "r", stdin) 38 #define gcd(a, b) __gcd(a, b) 39 #define lowbit(x) x & -x 40 #define IO iOS::sync_with_stdio(false) 41 42 using namespace std; 43 typedef long long LL; 44 typedef unsigned long long ULL; 45 const ULL seed = 13331; 46 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; 47 const int maxn = 1e6 + 7; 48 const int maxm = 8e6 + 10; 49 const int INF = 0x3f3f3f3f; 50 const int mod = 1e9 + 7; 51 52 struct Cost_MaxFlow { 53 int s, t, tot, maxflow, head[maxn], vis[maxn], pre[maxn], last[maxn]; 54 LL mincost, maxcost, dis[maxn], disf[maxn]; 55 struct Edge { 56 int v, w, nxt; 57 int cost; 58 } edge[maxm]; 59 queue<int> q; 60 61 void init() { 62 tot = 1; 63 mincost = maxcost = 0; 64 memset(head, -1, sizeof(head)); 65 } 66 67 void add(int u, int v, int f, int e) { 68 edge[++tot].v = v, edge[tot].nxt = head[u], head[u] = tot, edge[tot].w = f, edge[tot].cost = e; 69 edge[++tot].v = u, edge[tot].nxt = head[v], head[v] = tot, edge[tot].w = 0, edge[tot].cost = -e; 70 } 71 72 bool spfa_max() { 73 memset(dis, 0xef, sizeof(dis)); 74 q.push(s), dis[s] = 0, disf[s] = INFLL, pre[t] = -1; 75 while (!q.empty()) { 76 int u = q.front(); 77 q.pop(); 78 vis[u] = 0; 79 for (int i = head[u]; ~i; i = edge[i].nxt) { 80 int v = edge[i].v; 81 if (edge[i].w && dis[v] < dis[u] + edge[i].cost) { 82 dis[v] = dis[u] + edge[i].cost, last[v] = i, pre[v] = u; 83 disf[v] = min(disf[u], 1LL * edge[i].w); 84 if (!vis[v]) 85 vis[v] = 1, q.push(v); 86 } 87 } 88 } 89 return ~pre[t]; 90 } 91 92 void dinic_max() { 93 while (spfa_max()) { 94 int u = t; 95 maxflow += disf[t]; 96 maxcost += disf[t] * dis[t]; 97 while (u != s) { 98 edge[last[u]].w -= disf[t]; 99 edge[last[u] ^ 1].w += disf[t]; 100 u = pre[u]; 101 } 102 } 103 } 104 105 bool spfa_min() { 106 memset(dis, 0x3f, sizeof(dis)); 107 memset(vis, 0, sizeof(vis)); 108 memset(disf, 0x3f, sizeof(disf)); 109 q.push(s), dis[s] = 0, vis[s] = 1, pre[t] = -1; 110 while (!q.empty()) { 111 int u = q.front(); 112 q.pop(); 113 vis[u] = 0; 114 for (int i = head[u]; ~i; i = edge[i].nxt) { 115 int v = edge[i].v; 116 if (edge[i].w > 0 && dis[v] > dis[u] + edge[i].cost) { 117 dis[v] = dis[u] + edge[i].cost, pre[v] = u; 118 last[v] = i, disf[v] = min(disf[u], 1LL * edge[i].w); 119 if (!vis[v]) 120 vis[v] = 1, q.push(v); 121 } 122 } 123 } 124 return pre[t] != -1; 125 } 126 127 void dinic_min() { 128 while (spfa_min()) { 129 int u = t; 130 maxflow += disf[t]; 131 mincost += disf[t] * dis[t]; 132 while (u != s) { 133 edge[last[u]].w -= disf[t]; 134 edge[last[u] ^ 1].w += disf[t]; 135 u = pre[u]; 136 } 137 } 138 } 139 } F; 140 141 int n, W, a[maxn], cnt[maxn], sum; 142 143 void link(int L, int R) { 144 if (L == R) return; 145 int num = 0, mid = (L + R) / 2; 146 for (int i = L; i <= R; i++) cnt[++num] = a[i]; 147 sort(cnt + 1, cnt + 1 + num); 148 num = unique(cnt + 1, cnt + 1 + num) - cnt - 1; 149 for (int i = 1; i < num; i++) { 150 F.add(sum + i, sum + i + 1, INF, cnt[i + 1] - cnt[i]); 151 F.add(sum + i + 1, sum + i, INF, cnt[i + 1] - cnt[i]); 152 } 153 for (int i = L; i <= R; i++) { 154 if (i <= mid) { 155 int pos = lower_bound(cnt + 1, cnt + 1 + num, a[i]) - cnt; 156 F.add(sum + pos, i + n, 1, 0); 157 } else { 158 int pos = lower_bound(cnt + 1, cnt + 1 + num, a[i]) - cnt; 159 F.add(i, sum + pos, 1, 0); 160 } 161 } 162 sum += num; 163 link(L, mid), link(mid + 1, R); 164 } 165 166 int main() { 167 #ifndef ONLINE_JUDGE 168 FIN; 169 #endif 170 while (~sffi(n, W)) { 171 for (int i = 1; i <= n; i++) sfi(a[i]); 172 F.init(); 173 F.s = 0, F.t = 2 * n + 1; 174 sum = 2 * n + 1; 175 for (int i = 1; i <= n; i++) { 176 F.add(F.s, i, 1, 0); 177 F.add(i + n, F.t, 1, 0); 178 F.add(i, F.t, 1, W); 179 } 180 link(1, n); 181 F.dinic_min(); 182 printf("%lld ", F.mincost); 183 } 184 #ifndef ONLINE_JUDGE 185 cout << "Totle Time : " << (double) clock() / CLOCKS_PER_SEC << "s" << endl; 186 #endif 187 return 0; 188 }