1. 程式人生 > >TYVJP1666城市建設

TYVJP1666城市建設

這題寫的不明不白的

應該是Kruskal

因為我也沒太搞懂咋做

當我在廢話就好了

我們對於兩個本來就有邊的城市,考慮先在哪個城市建房 對於兩個城市i,j,我們先在i建房的代價是h[i](st[i]+st[j])+h[i](st[i]+1+st[j])+...+h[i](st[i]+ed[i]st[i]+st[j])h[i]*(st[i]+st[j])+h[i]*(st[i]+1+st[j])+...+h[i]*(st[i]+ed[i]-st[i]+st[j])

[i]+st[j]),化簡一下,可以得到h[i](ed[i]st[i])st[j]+h[i]*(ed[i]-st[i])*st[j]+(某等差數列),然後在建j的代價是h[j](st[j]+ed[i])+h[j](st[j]+1+ed[i])+...+h[j](st[j]+ed[j]st[j])h[j]*(st[j]+ed[i])+h[j]*(st[j]+1+ed[i])+...+h[j]*(st[j]+ed[j]-st[j]),化簡和上面一樣 先建j同理,然後我們發現,一個點後面那個**“某等差數列”**會被重複多次,所以我們先算前面的,後面的最後再加上,然後把兩種情況取min加到ans裡 對於沒有邊的城市,把上面的情況去掉等差數列,然後取min+兩邊還沒蓋房子時的人數和,當邊權去做最小生成樹

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lli long long int
using namespace std; const int M=100; lli n,m,ans; char map[M][M]; lli st[M],ed[M],co[M]; int fa[M],siz[M],cnt=1,tot; struct edge { lli fr,to,cos; bool friend operator < (edge a,edge b) {return a.cos<b.cos;} }e[M*M]; inline int read() { int x=0;char ch=getchar(); while (ch>'9'||ch<'0') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } inline int find(int x) { if (fa[x]!=x) return fa[x]=find(fa[x]); return x; } inline void unionn(int x,int y) { if (siz[x]<=siz[y]) siz[y]+=siz[x],fa[x]=y; else siz[x]+=siz[y],fa[y]=x; return ; } inline lli calc(int i,int k) { return co[i]*(ed[i]-st[i])*st[k]+co[k]*(ed[k]-st[k])*ed[i]; } inline void Kru() { for (int i=1;i<=tot&&cnt<n;i++) { int r1=find(e[i].fr); int r2=find(e[i].to); if (r1!=r2) cnt++,ans+=e[i].cos,unionn(r1,r2); } return ; } signed main() { n=read(); for (int i=1;i<=n;i++) st[i]=read(); for (int i=1;i<=n;i++) ed[i]=read(); for (int i=1;i<=n;i++) co[i]=read(); for (int i=1;i<=n;i++) fa[i]=i,siz[i]=1; for (int i=1;i<=n;i++) scanf("%s",map[i]+1); for (int i=1;i<=n;i++) for (int k=1;k<=n;k++) if (k>i) { if (map[i][k]=='Y') { int r1=find(i),r2=find(k); if (r1!=r2) cnt++,unionn(r1,r2); ans+=min(calc(i,k),calc(k,i)); } else { e[++tot].fr=i;e[tot].to=k; e[tot].cos=min(calc(i,k),calc(k,i)); } } m=read(); for (int i=1;i<=tot;i++) e[i].cos+=m*(st[e[i].fr]+st[e[i].to]); sort(e+1,e+tot+1);Kru(); for (int i=1;i<=n;i++) ans+=(st[i]-1+ed[i])*(ed[i]-st[i])/2*co[i]; cout<<ans; return 0; }