题解 AT4144 【[ARC098D] Donation】
command_block · · 题解
题意 : 给出一张
点
你可以从任意点开始旅程。你需要在所有点打卡一次,问初始时最少需要携带多少元。
其中,
#include<algorithm>
#include<cstdio>
#include<vector>
#define pb push_back
#define ll long long
#define MaxN 105000
using namespace std;
struct UFS{
int f[MaxN];
void Init(int n)
{for (int i=1;i<=n;i++)f[i]=i;}
int find(int u)
{return f[u]==u ? u : f[u]=find(f[u]);}
bool merge(int u,int v){
u=find(u);v=find(v);
if (u==v)return 0;
f[u]=v;return 1;
}
}F;
vector<int> g[MaxN],org[MaxN];
ll dp[MaxN],s[MaxN];
int c[MaxN],b[MaxN];
void pfs(int u)
{
s[u]=b[u];
for (int i=0;i<g[u].size();i++){
pfs(g[u][i]);
s[u]+=s[g[u][i]];
}
}
void dfs(int u)
{
if (!g[u].size())dp[u]=b[u]+c[u];
else dp[u]=1ll<<60;
for (int i=0,v;i<g[u].size();i++){
dfs(v=g[u][i]);
dp[u]=min(dp[u],s[u]-s[v]+max((ll)c[u],dp[v]));
}
}
bool cmp(int A,int B)
{return c[A]<c[B];}
int n,m,p[MaxN];bool vis[MaxN];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d%d",&c[i],&b[i]);
c[p[i]=i]=max(c[i]-b[i],0);
}for (int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
org[u].pb(v);org[v].pb(u);
}
sort(p+1,p+n+1,cmp);
F.Init(n);
for (int t=1;t<=n;t++){
int u=p[t];
for (int i=0,v;i<org[u].size();i++)
if (vis[v=org[u][i]]){
v=F.find(v);
if (F.merge(v,u))g[u].pb(v);
}
vis[u]=1;
}
pfs(p[n]);dfs(p[n]);
printf("%lld",dp[p[n]]);
return 0;
}