Hướng dẫn giải của VOI 11 Bài 6 - Nâng cấp mạng
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này
Code mẫu của flashmt
#include<iostream> #include<algorithm> #define fr(a,b,c) for(a=b;a<=c;a++) #define frr(a,b,c) for(a=b;a>=c;a--) #define maxn 100100 #define oo 1000000 using namespace std; struct rec{ int x,y,z; }; int n,m,lab[maxn],ok[maxn],sl,p[maxn],e[maxn][18],f[maxn][18],next[maxn]; int a[maxn*2],c[maxn*2],h[maxn],d[maxn],hh; rec b[maxn]; long long re; void sort(int l,int r) { int i=l,j=r,x=b[(i+j)/2].z,y; do { while (b[i].z>x) i++; while (b[j].z<x) j--; if (i<=j) { swap(b[i],b[j]); i++; j--; } } while (i<=j); if (i<r) sort(i,r); if (l<j) sort(l,j); } int get(int x) { if (lab[x]!=x) lab[x]=get(lab[x]); return lab[x]; } void visit(int x,int y) { e[x][0]=y; hh=max(hh,h[x]); int i; fr(i,p[x]+1,p[x+1]) if (a[i]!=y) { h[a[i]]=h[x]+1; d[a[i]]=c[i]; visit(a[i],x); } } int calc(int x,int y) { int i,lg,res=oo; if (h[x]<h[y]) swap(x,y); for (lg=0;1<<lg<=h[x];lg++); lg--; frr(i,lg,0) if (h[x]-(1<<i)>=h[y]) { res=min(res,f[x][i]); x=e[x][i]; } if (x==y) return res; frr(i,lg,0) if (e[x][i] && e[x][i]!=e[y][i]) { res=min(res,min(f[x][i],f[y][i])); x=e[x][i]; y=e[y][i]; } res=min(res,min(d[x],d[y])); return res; } int main() { int i,x,y,j,v=0,w=100001; cin >> n >> m; fr(i,1,m) scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].z); sort(1,m); fr(i,1,n) lab[i]=i; fr(i,1,m) { if (sl<n-1) { x=get(b[i].x); y=get(b[i].y); if (x!=y) { ok[i]=1; lab[y]=x; p[b[i].x]++; p[b[i].y]++; next[v]=i; v=i; ++sl; } else { next[w]=i; w=i; } } else { next[w]=i; w=i; } } fr(i,2,n+1) p[i]+=p[i-1]; i=next[0]; while (i) { a[p[b[i].x]]=b[i].y; c[p[b[i].x]--]=b[i].z; a[p[b[i].y]]=b[i].x; c[p[b[i].y]--]=b[i].z; i=next[i]; } visit(1,0); d[1]=oo; fr(i,1,n) f[i][0]=d[i]; for (j=1;1<<j<=hh;j++) fr(i,1,n) if (e[i][j-1]) { e[i][j]=e[e[i][j-1]][j-1]; f[i][j]=min(f[i][j-1],f[e[i][j-1]][j-1]); } else f[i][j]=oo; i=next[100001]; while (i) { re+=calc(b[i].x,b[i].y)-b[i].z; i=next[i]; } cout << re << endl; return 0; }
Code mẫu của happyboy99x
#include<iostream> #include<cstring> #include<vector> #include<algorithm> using namespace std; #define TR(v,i) for(__typeof((v).begin())i=(v).begin();i!=(v).end();++i) const int N = 1e5, LOG = 17, INF = 1e9; vector<vector<pair<int, int> > > mst; vector<pair<int, pair<int, int> > > edge; int n, m, mindist[N][LOG], par[N][LOG], sett[N], h[N], logn; void initSet() { for(int i = 0; i < n; ++i) sett[i] = i; } int getSet(int u) { return u == sett[u] ? u : sett[u] = getSet(sett[u]); } void enter() { cin >> n >> m; mst.resize(n); for(int i = 0; i < m; ++i) { int u, v, c; cin >> u >> v >> c; edge.push_back(make_pair(-c, make_pair(--u, --v))); } } void findMST() { initSet(); sort(edge.begin(), edge.end()); TR(edge, it) { int u = it->second.first, v = it->second.second, w = -it->first; if(getSet(u) != getSet(v)) { mst[u].push_back(make_pair(v, w)); mst[v].push_back(make_pair(u, w)); sett[sett[u]] = sett[v]; } } } void dfs(int u) { TR(mst[u], it) { int v = it->first, w = it->second; if(v != par[u][0]) { h[v] = h[u] + 1; par[v][0] = u; mindist[v][0] = w; dfs(v); } } } void initLCA() { logn = 0; while(1 << logn <= n) ++logn; --logn; for(int j = 1; 1 << j < n; ++j) for(int i = 0; i < n; ++i) if(par[i][j-1] != -1) { par[i][j] = par[par[i][j-1]][j-1]; mindist[i][j] = min(mindist[i][j-1], mindist[par[i][j-1]][j-1]); } } int getmin(int u, int v) { if(h[u] < h[v]) swap(u, v); int res = INF; for(int j = logn; j >= 0; --j) if(h[u] - (1 << j) >= h[v]) { res = min(res, mindist[u][j]); u = par[u][j]; } if(u == v) return res; for(int j = logn; j >= 0; --j) if(par[u][j] != par[v][j]) { res = min(res, min(mindist[u][j], mindist[v][j])); u = par[u][j]; v = par[v][j]; } return min(res, min(mindist[u][0], mindist[v][0])); } void solve() { long long res = 0; TR(edge, it) { int u = it->second.first, v = it->second.second, w = it->first; res += getmin(u, v) + w; } cout << res << "\n"; } int main() { ios::sync_with_stdio(false); enter(); findMST(); memset(par, -1, sizeof par); h[0] = 0; dfs(0); initLCA(); solve(); return 0; }
Code mẫu của ladpro98
{$MODE OBJFPC} program upgranet; uses math; type e=record x,y,w:longint; end; e2=record v,w:longint; end; const fi=''; maxn=100005; maxm=200005; maxL=trunc(ln(maxn)/ln(2))+1; var n,m,log,me:longint; a:array[1..maxm] of e; adj:array[1..maxm] of e2; link:array[1..maxm] of longint; lab,head,par,w,d:array[0..maxn] of longint; b,mi:array[0..maxn,0..maxL] of longint; choose,check:array[1..maxn] of boolean; procedure input; var inp:text; i:longint; begin assign(inp,fi);reset(inp); readln(inp,n,m); for i:=1 to m do readln(inp,a[i].x,a[i].y,a[i].w); close(inp); end; procedure sort(l,r:longint); var p,i,j:longint; t:e; begin if l>=r then exit; i:=l;j:=r; p:=a[random(r-l+1)+l].w; repeat while a[i].w>p do inc(i); while a[j].w<p do dec(j); if i<=j then begin if i<j then begin t:=a[i]; a[i]:=a[j]; a[j]:=t; end; inc(i);dec(j); end; until i>j; sort(l,j);sort(i,r); end; function root(u:longint):longint; begin if lab[u]<=0 then exit(u); result:=root(lab[u]); lab[u]:=result; end; procedure union(u,v:longint); begin if lab[u]<lab[v] then lab[v]:=u else begin if lab[u]=lab[v] then dec(lab[v]); lab[u]:=v; end; end; procedure kruskal; var i,x,y,c:longint; begin sort(1,m); for i:=1 to m do begin x:=root(a[i].x); y:=root(a[i].y); if x<>y then begin union(x,y); inc(c); choose[i]:=true; inc(me); adj[me].v:=y; adj[me].w:=a[i].w; link[me]:=head[x]; head[x]:=me; inc(me); adj[me].v:=x; adj[me].w:=a[i].w; link[me]:=head[y]; head[y]:=me; end; if c=n-1 then break; end; end; procedure dfs(i,p,c:longint); var j:longint; begin par[i]:=p; d[i]:=d[p]+1; w[i]:=c; check[i]:=true; j:=head[i]; while j>0 do begin if not check[adj[j].v] then dfs(adj[j].v,i,adj[j].w); j:=link[j]; end; end; procedure initLCA; var i,j:longint; begin log:=trunc(ln(n)/ln(2))+1; for i:=0 to n do begin b[i,0]:=par[i]; mi[i,0]:=w[i]; end; for j:=1 to log do for i:=0 to n do begin b[i,j]:=b[b[i,j-1],j-1]; mi[i,j]:=min(mi[i,j-1],mi[b[i,j-1],j-1]); end; end; function getbit(i,j:longint):longint; begin exit(i shr (j-1) and 1); end; function lca(u,v:longint):longint; var i,res,t:longint; begin res:=high(longint); if d[u]>=d[v] then begin if d[u]>d[v] then begin t:=d[u]-d[v]; for i:=log downto 1 do if getbit(t,i)=1 then begin res:=min(res,mi[u,i-1]); u:=b[u,i-1]; end; end; if u=v then exit(res); for i:=log downto 0 do begin if b[u,i]<>b[v,i] then begin res:=min(res,mi[u,i]); res:=min(res,mi[v,i]); u:=b[u,i]; v:=b[v,i]; end; if b[u,0]=b[v,0] then res:=min(res,min(mi[u,0],mi[v,0])); end; exit(res); end else exit(lca(v,u)); end; procedure output; var i:longint; res:int64; begin res:=0; for i:=1 to m do if not choose[i] then inc(res,lca(a[i].x,a[i].y)-a[i].w); write(res); end; begin input; kruskal; dfs(1,0,0); initLCA; output; end.
Code mẫu của RR
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <vector> #include <set> #include <map> #include <stack> #include <queue> #include <string> #include <deque> #include <complex> #define FOR(i,a,b) for(int i=(a),_b=(b); i<=_b; i++) #define FORD(i,a,b) for(int i=(a),_b=(b); i>=_b; i--) #define REP(i,a) for(int i=0,_a=(a); i<_a; i++) #define ll long long #define F first #define S second #define PB push_back #define MP make_pair using namespace std; const double PI = acos(-1.0); //Buffer reading int INP,AM; #define BUFSIZE (1<<10) char BUF[BUFSIZE+1], *inp=BUF; #define GETCHAR(INP) { \ if(!*inp) { \ fread(BUF,1,BUFSIZE,stdin); \ inp=BUF; \ } \ INP=*inp++; \ } #define DIG(a) (((a)>='0')&&((a)<='9')) #define GN(j) { \ AM=0;\ GETCHAR(INP); while(!DIG(INP) && INP!='-') GETCHAR(INP);\ if (INP=='-') {AM=1;GETCHAR(INP);} \ j=INP-'0'; GETCHAR(INP); \ while(DIG(INP)){j=10*j+(INP-'0');GETCHAR(INP);} \ if (AM) j=-j;\ } //End of buffer reading int n, m, lab[100111]; pair< int, pair<int,int> > e[100111]; vector<pair<int,int> > ke[100111]; int getRoot(int u) { if (lab[u] < 0) return u; return lab[u] = getRoot(lab[u]); } void merge(int u, int v) { int x = lab[u] + lab[v]; if (lab[u] < lab[v]) { lab[u] = x; lab[v] = u; } else { lab[v] = x; lab[u] = v; } } int father[22][100111], nn[22][100111], d[100111]; void dfs(int u, int fu) { REP(i,ke[u].size()) { int v = ke[u][i].F; if (v == fu) continue; father[0][v] = u; nn[0][v] = ke[u][i].S; d[v] = d[u] + 1; dfs(v, u); } } void init() { FOR(i,1,20) FOR(u,1,n) { int v = father[i-1][u]; if (v != -1) { father[i][u] = father[i-1][v]; nn[i][u] = min(nn[i-1][u], nn[i-1][v]); } } } int get(int u, int v) { if (u == v) return 0; if (d[u] < d[v]) swap(u,v); int res = 1000111000; FORD(i,20,0) if (father[i][u] >= 0 && d[father[i][u]] >= d[v]) { res = min(res, nn[i][u]); u = father[i][u]; } if (u == v) return res; FORD(i,20,0) if (father[i][u] != father[i][v]) { res = min(res, nn[i][u]); res = min(res, nn[i][v]); u = father[i][u]; v = father[i][v]; } res = min(res, nn[0][u]); res = min(res, nn[0][v]); return res; } bool mst[100111]; int main() { // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); GN(n); GN(m); REP(i,m) { GN(e[i].S.F); GN(e[i].S.S); GN(e[i].F); } sort(e, e+m); memset(lab, -1, sizeof lab); FORD(i,m-1,0) { int u = e[i].S.F, v = e[i].S.S, c = e[i].F; u = getRoot(u); v = getRoot(v); if (u == v) continue; merge(u, v); u = e[i].S.F, v = e[i].S.S; ke[u].PB(MP(v,c)); ke[v].PB(MP(u,c)); mst[i] = true; } // cout << endl; memset(father, -1, sizeof father); dfs(1, -1); init(); ll res = 0; FORD(i,m-1,0) if (!mst[i]) { int u = e[i].S.F, v = e[i].S.S; // cout << u << ' ' << v << ' ' << get(u,v) << endl; res += get(u, v) - e[i].F; } cout << res << endl; return 0; }
Code mẫu của skyvn97
#include<algorithm> #include<cstdio> #include<iostream> #include<queue> #include<vector> #define MAX 100100 #define FOR(i,a,b) for (int i=(a);i<=(b);i=i+1) #define FORD(i,b,a) for (int i=(b);i>=(a);i=i-1) #define FORE(i,v) for (__typeof((v).begin()) i=(v).begin();i!=(v).end();i++) #define fi first #define se second using namespace std; typedef pair<int,int> ii; typedef pair<int,ii> pii; const int INF=(int)1e9+7; pii e[MAX]; bool mst[MAX]; vector<ii> g[MAX]; ii p[MAX][19]; int h[MAX]; class DSU { private: vector<int> lab; int find(int x) { if (lab[x]<0) return (x); lab[x]=find(lab[x]); return (lab[x]); } public: DSU() { lab=vector<int>(); } DSU(int _n) { lab=vector<int>(_n+7,-1); } bool join(int a,int b) { int x=find(a); int y=find(b); if (x==y) return (false); lab[y]=x; return (true); } }; DSU dsu; int m,n; void loadgraph(void) { scanf("%d",&n); scanf("%d",&m); FOR(i,1,m) { int u,v,w; scanf("%d",&u); scanf("%d",&v); scanf("%d",&w); e[i]=pii(w,ii(u,v)); } dsu=DSU(n); h[0]=-1; } void loadtree(void) { sort(e+1,e+m+1,greater<pii>()); FOR(i,1,m) { if (dsu.join(e[i].se.fi,e[i].se.se)) { int u=e[i].se.fi; int v=e[i].se.se; int w=e[i].fi; g[u].push_back(ii(v,w)); g[v].push_back(ii(u,w)); } else (mst[i]=true); } } void visit(int u) { FORE(it,g[u]) if (it->fi!=p[u][0].fi) { int v=it->fi; p[v][0]=ii(u,it->se); h[v]=h[u]+1; visit(v); } } void setupLCA(void) { visit(1); FOR(j,1,18) FOR(i,1,n) p[i][j]=ii(p[p[i][j-1].fi][j-1].fi,min(p[i][j-1].se,p[p[i][j-1].fi][j-1].se)); } int mindis(int u,int v) { if (h[u]<h[v]) return (mindis(v,u)); int ret=INF; FORD(j,18,0) if (h[p[u][j].fi]>=h[v]) { ret=min(ret,p[u][j].se); u=p[u][j].fi; } if (u==v) return (ret); FORD(j,18,0) if (p[u][j].fi!=p[v][j].fi) { ret=min(ret,p[u][j].se); ret=min(ret,p[v][j].se); u=p[u][j].fi; v=p[v][j].fi; } ret=min(ret,p[u][0].se); ret=min(ret,p[v][0].se); return (ret); } void process(void) { long long res=0; FOR(i,1,m) if (mst[i]) { int u=e[i].se.fi; int v=e[i].se.se; int w=e[i].fi; res+=mindis(u,v)-w; } cout << res; } int main(void) { loadgraph(); loadtree(); setupLCA(); process(); return 0; }
Bình luận