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;
}
posted @ 2021-01-04 18:14  zjjws  阅读(62)  评论(0编辑  收藏  举报