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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 }

 

以上是关于[XSY 1145] 网络战争 平面最近点对 最小割树的主要内容,如果未能解决你的问题,请参考以下文章

平面最近点对问题

平面最近点对

平面最近点对

平面最近点对

Luogu 1429 平面最近点对 | 平面分治

Luogu P1429 平面最近点对 分治By cellur925