Data-2021-01-02_cly
cly 讲的时候,大部分时间我都掉线了,所以会做的并不多。
ARC098-F
倒着考虑,然后考虑钱的数量 \(m\) 的变化:\(m\to\max(m+b_i,a_i)\),那么也就是:\(m\to \max(m,a_i-b_i)+b_i\)。
于是就可以按照 \(\max(a_u-b_u,a_v-b_v)\) 对边进行排序,选取这个值最小的 \(n-1\) 条边,建出 Kruskal 重构树,然后 dfs 一遍求其值即可(其实是 DP)。
int n,m;
int a[N];
int b[N];
struct gyq
{
int x,y,v;
inline void init()
{
x=rin();y=rin();
v=max(a[x]-b[x],a[y]-b[y]);
return;
}
}c[N];
inline bool myru_gyq(gyq x,gyq y){return x.v<y.v;}
int f[N<<1];
inline int find(int x){return (f[x]==x)?(x):(f[x]=find(f[x]));}
int ls[N<<1];
int rs[N<<1];
LL v[N<<1];
LL sum[N<<1];
inline LL dfs(int x)
{
if(x<=n){sum[x]=b[x];return a[x];}
LL s_1=dfs(ls[x]),s_2=dfs(rs[x]);
sum[x]=sum[ls[x]]+sum[rs[x]];
return min(min(max(s_1,v[x])+sum[rs[x]],max(s_2,v[x])+sum[ls[x]]),v[x]+sum[x]);
}
int main()
{
int i,j;
n=rin();m=rin();
for(i=1;i<=n;i++)a[i]=rin(),b[i]=rin(),a[i]=max(a[i],b[i]);
for(i=1;i<=m;i++)c[i].init();
sort(c+1,c+m+1,myru_gyq);
int nam=n;
for(i=(n<<1);i>=1;i--)f[i]=i;
for(i=1;i<=m;i++)
{
int x=c[i].x,y=c[i].y;
if(find(x)==find(y))continue;
nam++;
ls[nam]=find(x);
rs[nam]=find(y);
v[nam]=c[i].v;
f[find(x)]=f[find(y)]=nam;
}
if(nam!=((n<<1)-1))puts("El Psy Congroo");
printf("%lld\n",dfs(nam));
return 0;
}
$$\texttt{Dirty Deeds Done Dirt Cheap}$$