日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图的分块

發(fā)布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图的分块 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

基本思想是按點的度數(shù)劃分為重點(deg>=sqrt(m))和輕點(deg<sqrt(m)),?輕點暴力更新, 重點只更新鄰接的重點.

?

?

例1. hdu 4858 項目管理

該題算簡單入門了.

#include <iostream> #include <algorithm> #include <math.h> #include <cstdio> #include <vector> #define pb push_back #define REP(i,a,n) for(int i=a;i<=n;++i) using namespace std; typedef long long ll;const int N = 1e5+10, INF = 0x3f3f3f3f; int n, m, q, sqn; int deg[N], u[N], v[N]; ll sum[N], val[N]; vector<int> g[N];void work() {scanf("%d%d", &n, &m), sqn = sqrt(m);REP(i,1,n) g[i].clear(), deg[i]=sum[i]=val[i]=0;REP(i,1,m) {scanf("%d%d", u+i, v+i);++deg[u[i]], ++deg[v[i]];}REP(i,1,m) {if (deg[u[i]]>=sqn&&deg[v[i]]>=sqn) {g[u[i]].pb(v[i]),g[v[i]].pb(u[i]);}if (deg[u[i]]<sqn) g[u[i]].pb(v[i]);if (deg[v[i]]<sqn) g[v[i]].pb(u[i]);}scanf("%d", &q);REP(i,1,q) {int op, x, v;scanf("%d%d", &op, &x);if (op==0) {scanf("%d", &v);val[x] += v;for (int y:g[x]) if (deg[y]>=sqn) sum[y]+=v;} else {ll ans = 0;if (deg[x]<sqn) for (int y:g[x]) ans += val[y];else ans = sum[x];printf("%lld\n", ans);}} }int main() {int t;scanf("%d", &t);REP(i,1,t) work(); }

?

?

例2: hdu 4467 Graph

大意: 每個點都有一個顏色0或1, 每次詢問求所有端點顏色為x,y的邊權(quán)和, 每次修改翻轉(zhuǎn)一個點的顏色.

思路還是同上題, 對于輕點的修改, 直接暴力. 對于重點的修改只暴力改重點之間的邊, 然后再$O(1)$更新重點與輕點的邊. 但本題比較卡常, 需要將邊離散化去重一下.

其中$ans$用于記錄答案, $val$用于記錄每個重點與輕點相連邊權(quán)和.

#include <iostream> #include <algorithm> #include <math.h> #include <cstdio> #include <set> #include <string> #include <vector> #define pb push_back #define REP(i,a,n) for(int i=a;i<=n;++i) using namespace std; typedef long long ll;const int N = 1e5+10, INF = 0x3f3f3f3f; int n, m, sqn, col[N]; struct _ {int u,v;ll w;bool operator < (const _ & rhs) const {if (u==rhs.u) return v<rhs.v;return u<rhs.u;} } e[N]; vector<_> g[N]; ll ans[3], val[N][2]; int deg[N];void update(int x) {for (_ e:g[x]) {ans[col[x]+col[e.v]]-=e.w;ans[(col[x]^1)+col[e.v]]+=e.w;if (deg[x]<sqn) {val[e.v][col[x]]-=e.w;val[e.v][col[x]^1]+=e.w;}}if (deg[x]>=sqn) {ans[col[x]]-=val[x][0];ans[col[x]+1]-=val[x][1];ans[col[x]^1]+=val[x][0];ans[(col[x]^1)+1]+=val[x][1];}col[x] ^= 1; }void work() {REP(i,1,n) scanf("%d", col+i);REP(i,1,n) val[i][0]=val[i][1]=deg[i]=0, g[i].clear();REP(i,0,2) ans[i]=0;REP(i,1,m) {scanf("%d%d%lld", &e[i].u, &e[i].v, &e[i].w);if (e[i].u>e[i].v) swap(e[i].u,e[i].v);}sort(e+1,e+1+m);int now = 0;REP(i,1,m) {if (e[i].u!=e[now].u||e[i].v!=e[now].v) e[++now]=e[i];else e[now].w += e[i].w;}m = now, sqn = sqrt(m);REP(i,1,m) { ans[col[e[i].u]+col[e[i].v]] += e[i].w;++deg[e[i].u],++deg[e[i].v];}REP(i,1,m) {if (deg[e[i].u]>=sqn&&deg[e[i].v]>=sqn) {g[e[i].u].pb({0,e[i].v,e[i].w});g[e[i].v].pb({0,e[i].u,e[i].w});}if (deg[e[i].u]<sqn) g[e[i].u].pb({0,e[i].v,e[i].w});if (deg[e[i].v]<sqn) g[e[i].v].pb({0,e[i].u,e[i].w});}REP(x,1,n) if (deg[x]<sqn) { for (_ e:g[x]) {if (deg[e.v]>=sqn) val[e.v][col[x]]+=e.w;}}int q;scanf("%d", &q);REP(i,1,q) {char s[15];int x, y;scanf("%s%d", s, &x);if (*s=='A') {scanf("%d", &y);printf("%lld\n", ans[x+y]);} else update(x);} }int main() {for (int kase = 1; ~scanf("%d%d", &n, &m); ++kase) {printf("Case %d:\n", kase);work();} }

?

轉(zhuǎn)載于:https://www.cnblogs.com/uid001/p/10434786.html

總結(jié)

以上是生活随笔為你收集整理的图的分块的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。