题意:
n 个排成一列的哨站要进行通信。第 i 个哨站的频段为 ai。
每个哨站 ii 需要选择以下二者之一:
1.直接连接到控制中心,代价为 W;2.连接到前面的某个哨站 j(j|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 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include <string> 9 #include 10 #include 11 #include 12 #include 13 #include 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("******\n") 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\n", F.mincost); 183 } 184 #ifndef ONLINE_JUDGE 185 cout << "Totle Time : " << (double) clock() / CLOCKS_PER_SEC << "s" << endl; 186 #endif 187 return 0; 188 }