zoukankan      html  css  js  c++  java
  • 「SNOI2019」通信 分治优化费用流建图

    题意:

    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 }
    View Code
  • 相关阅读:
    python中使用easygui
    SQL Server: Windows Firewall with Advanced Security
    xxx while the managed IDbConnection interface was being used: Login failed for user xxx
    忽略PyCharm4中特定的警告提示信息
    C#如何生成一个随机种子for Random?
    PSSecurityException之PowerShell权限设置
    如何用CSS进行开发
    为什么不建议用table进行布局
    Batch脚本获取日期SET YEAR=%date:~10,4%
    Java实现邮箱找回密码
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/11541090.html
Copyright © 2011-2022 走看看