「BZOJ1232」 [Usaco2008Nov]安慰奶牛cheer
阿新 • • 發佈:2019-03-10
problem int register ble ace mat 最終 == ring
「BZOJ1232」 [Usaco2008Nov]安慰奶牛cheer
problem
Solution
最終的圖顯然是一棵樹
把每條邊視作兩條有向邊。在樹的情況下,一定需要走完所有的有向邊。除了出發點以外,走一條有向邊\((u,v)\)對答案的貢獻為\(w(u,v)+c[v]\),亦即每條無向邊對答案的貢獻為\(w(u,v)*2+c[u]+c[v]\),將其作為邊權跑最小生成樹。生成樹的權值加上最小的點權即為答案
Code
#include <cstdio> #include <iostream> #include <algorithm> #include <cstdlib> #include <cstring> #include <cmath> #define maxn 10005 #define maxm 100005 using namespace std; typedef long long ll; int n,m; int c[maxn]; int ans; struct edge { int u,v,w; }g[maxm]; int prt[maxn]; int getroot(int u) { return prt[u]==u?u:prt[u]=getroot(prt[u]); } bool cmp(const edge &a,const edge &b) { return a.w<b.w; } void Kruskal() { for(register int i=1;i<=n;++i) prt[i]=i; sort(g+1,g+m+1,cmp); int cnt=0; for(register int i=1;i<=m;++i) { int r1=getroot(g[i].u),r2=getroot(g[i].v); if(r1!=r2) { prt[r1]=r2; ++cnt; ans+=g[i].w; } if(cnt==n-1) return; } } int main() { scanf("%d%d",&n,&m); for(register int i=1;i<=n;++i) scanf("%d",&c[i]); for(register int i=1;i<=m;++i) { scanf("%d%d%d",&g[i].u,&g[i].v,&g[i].w); g[i].w=g[i].w*2+c[g[i].u]+c[g[i].v]; } Kruskal(); sort(c+1,c+n+1); printf("%d",ans+c[1]); return 0; }
「BZOJ1232」 [Usaco2008Nov]安慰奶牛cheer