[XSY 1145] 网络战争 平面最近点对 最小割树

  码农题.

  LEN 开到 1000 比较稳.

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cctype>
  5 #include <algorithm>
  6 #include <vector>
  7 using namespace std;
  8 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
  9 #define LL long long
 10 inline int rd(void) {
 11     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1;
 12     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f;
 13 }
 14
 15 const int N = 50005;
 16 const int Ni = 2005;
 17 const int Mi = 4005;
 18 const int S = 100005;
 19 const int INF = ~0u>>2;
 20 const int LEN = 1000;
 21
 22 int n, Start[N];
 23
 24 int List[Ni], tmp[Ni]; bool Vis[Ni];
 25
 26 struct Edge { int v, f, nx; }mp[Mi]; int tot, hd[Ni];
 27 int q[Ni], qh, qt, Lev[Ni];
 28 inline void Init(int x, int y, int w) {
 29     mp[++tot] = (Edge){y, w, hd[x]}, hd[x] = tot;
 30     mp[++tot] = (Edge){x, w, hd[y]}, hd[y] = tot;
 31 }
 32
 33 struct E { int v, d; }; vector<E> g[S];
 34 inline void Add(int x, int y, int w) { g[x].push_back((E){y, w}), g[y].push_back((E){x, w}); }
 35
 36 bool BFS(int s, int t) {
 37     memset(q, 0, sizeof q), qh = qt = 0, memset(Lev, -1, sizeof Lev);
 38     q[++qt] = s, Lev[s] = 0;
 39     while (qh != qt) {
 40         int x = q[++qh];
 41         for (int k = hd[x]; k > 0; k = mp[k].nx)
 42             if (mp[k].f > 0 && Lev[mp[k].v] == -1) {
 43                 Lev[mp[k].v] = Lev[x]+1;
 44                 if (mp[k].v == t) return true;
 45                 q[++qt] = mp[k].v;
 46             }
 47     }
 48     return false;
 49 }
 50 int DFS(int x, int t, int flow) {
 51     if (x == t) return flow;
 52     int sum = 0;
 53     for (int k = hd[x]; k > 0; k = mp[k].nx)
 54         if (mp[k].f > 0 && Lev[mp[k].v] == Lev[x]+1) {
 55             int tmp = DFS(mp[k].v, t, min(flow, mp[k].f));
 56             if (tmp > 0) {
 57                 mp[k].f -= tmp, mp[k^1].f += tmp;
 58                 sum += tmp, flow -= tmp;
 59                 if (!flow) break;
 60             }
 61             else Lev[mp[k].v] = INF;
 62         }
 63     return sum;
 64 }
 65 void Paint(int x) {
 66     Vis[x] = true;
 67     for (int k = hd[x]; k > 0; k = mp[k].nx)
 68         if (mp[k].f > 0 && !Vis[mp[k].v])
 69             Paint(mp[k].v);
 70 }
 71 void Solve(int Bg, int L, int R) {
 72     if (L == R) return;
 73
 74     int s = List[L], t = List[R];
 75     for (int i = 2; i <= tot; i += 2)
 76         mp[i].f = mp[i^1].f = (mp[i].f + mp[i^1].f) >> 1;
 77
 78     int sum = 0;
 79     while (BFS(s, t))
 80         sum += DFS(s, t, INF);
 81     memset(Vis, false, sizeof Vis);
 82     Paint(s);
 83
 84     Add(Bg + s, Bg + t, sum);
 85     F(i, L, R) tmp[i] = List[i];
 86     int curL = L, curR = R;
 87     F(i, L, R)
 88         Vis[tmp[i]] ? List[curL++] = tmp[i] : List[curR--] = tmp[i];
 89     Solve(Bg, L, curL-1);
 90     Solve(Bg, curR+1, R);
 91 }
 92
 93 void Build(int Bg, int n, int m) {
 94     tot = 1, memset(hd, 0, sizeof hd);
 95     F(i, 1, m) {
 96         int x = rd(), y = rd(), w = rd();
 97         Init(x, y, w);
 98     }
 99
100     F(i, 1, n) List[i] = i;
101     random_shuffle(List+1, List+n+1);
102     Solve(Bg, 1, n);
103 }
104
105 int val[N], id[N], ord[N];
106 struct point { int x, y; }p[N];
107
108 inline bool cmpx(int i, int j) { return p[i].x < p[j].x; }
109 inline bool cmpy(int i, int j) { return p[i].y < p[j].y; }
110 inline LL Dist(point A, point B) { return 1LL * (A.x - B.x) * (A.x - B.x) + 1LL * (A.y - B.y) * (A.y - B.y); }
111 void Up(void) {
112     F(i, 1, n) {
113         int L = max(1, i-LEN), R = min(n, i+LEN), cur = ord[i];
114         F(j, L, R) if (i != j) {
115             int Dx = Dist(p[cur], p[id[cur]]), Dy = Dist(p[cur], p[ord[j]]);
116             if (Dx > Dy || (Dx == Dy && id[cur] > ord[j]))
117                 id[cur] = ord[j];
118         }
119     }
120 }
121
122 int par[S], key[S], dep[S];
123 void Prework(int x) {
124     for (vector<E>::iterator it = g[x].begin(); it != g[x].end(); it++)
125         if (par[x] != it->v) {
126             if (par[it->v] > 0) { key[it->v] += it->d; continue; }
127             par[it->v] = x, key[it->v] = it->d, dep[it->v] = dep[x]+1;
128             Prework(it->v);
129         }
130 }
131 inline int Query(int x, int y) {
132     int res = INF;
133     if (dep[x] < dep[y]) swap(x, y);
134     for (; dep[x] != dep[y]; x = par[x])
135         res = min(res, key[x]);
136     for (; x != y; x = par[x], y = par[y])
137         res = min(res, key[x]), res = min(res, key[y]);
138     // If x and y is not connected, the answer should be zero
139     // and I can get zero through ( par[root] = 0, key[root] = 0 )
140     return res;
141 }
142
143 int main(void) {
144     #ifndef ONLINE_JUDGE
145         freopen("network.in", "r", stdin);
146     #endif
147
148     n = rd();
149     F(j, 1, n) {
150         int x = rd(); p[j] = (point){x, rd()};
151         val[j] = rd();
152
153         int ni = rd(), mi = rd();
154         Start[j+1] = Start[j] + ni;
155
156         Build(Start[j], ni, mi);
157     }
158
159     if (n != 1) {
160         F(i, 1, n) id[i] = 1 + (i == 1);
161         F(i, 1, n) ord[i] = i;
162         sort(ord+1, ord+n+1, cmpx);
163         Up();
164         sort(ord+1, ord+n+1, cmpy);
165         Up();
166         F(i, 1, n)
167             Add(Start[i]+1, Start[id[i]]+1, val[i]);
168     }
169
170     F(i, 1, Start[n+1])
171         if (!key[i]) dep[i] = 1, Prework(i);
172
173     int q = rd();
174     F(t, 1, q) {
175         int ta = rd(), tb = rd(), qa = rd(), qb = rd();
176         printf("%d\n", Query(Start[ta] + qa, Start[tb] + qb));
177     }
178
179     return 0;
180 }
时间: 2024-10-19 14:47:58

[XSY 1145] 网络战争 平面最近点对 最小割树的相关文章

网络战争 [KD-Tree+最小割树]

题面 思路 首先吐槽一下: 这题是什么东西啊??出题人啊,故意拼题很有意思吗??还拼两个这么毒瘤的东西???? 10K代码了解一下???? 然后是正经东西 首先,本题可以理解为这样: 给定$n$个块,每个块有一个根,每个根只会主动连出去一条无向边,每次求两点最小割 那么,我们显然可以把每个块内的最小割树建立出来,同时把块的根之间的最小割树也建立出来 如果询问点在同一个块里面,显然可以直接最小割树处理 否则就是两边的点到块根的最小割和两个块根之间的最小割的最小值 所以,我们先对于所有的块根,建出K

[2016北京集训试题6]网络战争-[最小割树(网络流)+kd-tree+倍增]

Description A 联邦国有 N 个州,每个州内部都有一个网络系统,有若干条网络线路,连接各个 州内部的城市. 由于 A 国的州与州之间的关系不是太好,每个州都只有首府建立了到别的州的网络.具体来说,每个州的首府都只主动地建立了一条网络线路,连接到距离最近的州的 首府.(欧氏距离.如果有多个,选择标号最小的去连接) B 国探知了 A 国的网络线路分布情况,以及攻陷每条网络线路所需花费的代价,B 国首脑想知道断开 A 国某两个城市之间的网络连接,所需的最少代价.请你计算出来告 诉他. 注:

[XSY 1129] flow 最小割 树链剖分 线段树优化建图

题意 给定一张 $N$ 个点的有根树, $1$ 为树的根. 每个点有点权 $V[i]$ . 若 $V[i] > 0$ , 则可以获得 $V[i]$ 的收益; 若 $V[i] < 0$ , 则需要付出 $V[i]$ 的代价. 如果选择了某个点 $x$ , 且它的连续的 $K$ 个祖先中存在一个没有选, 则需要付出 $P_x$ 的代价. 最大化总收益. 分析 将 树链剖分 + zkw线段树 嵌入网络中, 跑最小割. 实现 #include <cstdio> #include <c

网络战争

PDF题面 我曾经以为$LCT$已经足够毒瘤,直到我写了树套树. 我曾经又以为树套树已经足够毒瘤,直到我写了这道题. $hhh$ 这道题大概分为三个部分 一.首府之间最近点相连 由于$N$不超过$10^5$,且$|X_i|,|Y_i|$均匀随机,我们大可以使用$KD-Tree$,即先以每个州首府坐标建出$KD-Tree$,再枚举每一个点进行在$KD-Tree$中搜索,由于坐标随机,复杂度期望为$O(N\log n)$. 这里有一个性质,那就是一定不存在重边以外的简单环.因为如果存在,那么你一定能

hdu1007 平面最近点对(暴力+双线程优化)

突发奇想,用双线程似乎可以优化一些暴力 比如说平面最近点对这个题目,把点复制成2份 一份按照x排序,一份按照y排序 然后双线程暴力处理,一份处理x,一份处理y 如果数据利用x递减来卡,那么由于双线程,它卡不住y 如果数据利用y递减来卡,那么卡不住x 这样暴力n^2就可以过了 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algori

平面最近点对(分治nlogn)

平面最近点对,是指给出平面上的n个点,寻找点对间的最小距离 首先可以对按照x为第一关键字排序,然后每次按照x进行分治,左边求出一个最短距离d1,右边也求出一个最短距离d2,那么取d=min(d1, d2) 然后只需考虑横跨左右两侧的点,不妨枚举左侧的点pi 那么很显然的是如果pi距离中间的点超过了d,便可以直接舍去,只需考虑距离中间点小于d的点 这样一来就可以对每个pi画一个边长为2d的正方形,易证,矩形内最多存在8个点. 那么关键问题就是要快速找这8个点 朴素做法是对分治后的点进行快排,这样复

POJ 3714 Raid(平面最近点对)

解题思路: 分治法求平面最近点对,点分成两部分,加个标记就好了. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <iomanip>

图论(网络流,分数规划):COGS 2047. [ZOJ2676]网络战争

2047. [ZOJ2676]网络战争 ★★★   输入文件:networkwar.in   输出文件:networkwar.out   评测插件 时间限制:5 s   内存限制:32 MB [题目描述] Byteland的网络是由n个服务器和m条光纤组成的,每条光纤连接了两个服务器并且可以双向输送信息.这个网络中有两个特殊的服务器,一个连接到了全球的网络,一个连接到了总统府,它们的编号分别是1和N. 最近一家叫做Max Traffic的公司决定控制几条网络中的光纤,以使他们能够掌握总统府的的上

平面最近点对

HDU 1007 求平面最近点对距离的一半 #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; const double eps = 1e-7; const int MAXN = 100010; const double INF = 1e20; struct Point