Input
7 7 8 1 3 2 5 2 4 6 5 6 1 8 1 2 9 5 4 3 3 4 10 3 7 4
Output
1 24
一看就知道是个什么套路
记录每个点的siz , dis。在父子节点间考虑转移。
然后搞了个代码,过了个极水的样例
1 #include<stdio.h> 2 #define For(i,a,b) for(register int i=(a);i<=(b);i++) 3 using namespace std; 4 const int maxn=7e5+10; 5 int n,a[maxn],head[maxn],cnt,siz[maxn],dis[maxn],ans=1; 6 long long del[maxn],tot; 7 struct Edge{ 8 int v,nxt,w; 9 }edge[maxn<<1]; 10 inline void add(int u,int v,int w){ 11 edge[++cnt].v=v,edge[cnt].w=w,edge[cnt].nxt=head[u],head[u]=cnt; 12 } 13 inline void pre(int p,int fa){ 14 siz[p]=1,tot+=dis[p]; 15 for(int i=head[p];i;i=edge[i].nxt){ 16 int v=edge[i].v;if(v==fa) continue; 17 dis[v]=dis[p]+edge[i].w; 18 pre(v,p);siz[p]+=siz[v]; 19 } 20 } 21 inline void dfs(int p,int fa){ 22 for(int i=head[p];i;i=edge[i].nxt){ 23 int v=edge[i].v;if(v==fa) continue; 24 del[v]=del[fa]+(n-siz[v])*edge[i].w-siz[v]*edge[i^1].w; 25 dfs(v,p); 26 } 27 } 28 signed main(){ 29 scanf("%d",&n); 30 For(i,1,n) scanf("%d",&a[i]); 31 For(i,2,n){ 32 int b,c,d;scanf("%d%d%d",&b,&c,&d); 33 add(b,c,d-a[b]),add(c,b,d-a[c]); 34 } 35 pre(1,1); 36 dfs(1,1); 37 For(i,1,n){ 38 if(del[i]<del[ans]) ans=i; 39 } 40 printf("%d %d\n",ans,tot+del[ans]); 41 }
然后爆0。比如上面那个数据就没过去。
发现算法没错。
int cnt;
从零开始的cnt竟然用^1来搞反向边,我……
然后再来一发,爆了int
呃呃呃我开了long long啊
printf("%d %d\n",ans,del[ans]);
改成lld, A了,我……
1 #include<stdio.h> 2 #define For(i,a,b) for(register int i=(a);i<=(b);i++) 3 using namespace std; 4 const int maxn=7e5+10; 5 int n,a[maxn],head[maxn],cnt=1,siz[maxn],ans=1; 6 long long dis[maxn],del[maxn]; 7 struct Edge{ 8 int v,nxt,w; 9 }edge[maxn<<1]; 10 inline void add(int u,int v,int w){ 11 edge[++cnt].v=v,edge[cnt].w=w,edge[cnt].nxt=head[u],head[u]=cnt; 12 } 13 inline void pre(int p,int fa){ 14 siz[p]=1,del[1]+=dis[p]; 15 for(int i=head[p];i;i=edge[i].nxt){ 16 int v=edge[i].v;if(v==fa) continue; 17 dis[v]=dis[p]+edge[i].w; 18 pre(v,p); 19 siz[p]+=siz[v]; 20 } 21 } 22 inline void dfs(int p,int fa){ 23 for(int i=head[p];i;i=edge[i].nxt){ 24 int v=edge[i].v;if(v==fa) continue; 25 del[v]=del[p]+(n-siz[v])*edge[i^1].w-(siz[v])*edge[i].w; 26 dfs(v,p); 27 } 28 } 29 signed main(){ 30 scanf("%d",&n); 31 For(i,1,n) scanf("%d",&a[i]); 32 For(i,2,n){ 33 int b,c,d;scanf("%d%d%d",&b,&c,&d); 34 add(b,c,d-a[b]),add(c,b,d-a[c]); 35 } 36 pre(1,1); 37 dfs(1,1); 38 For(i,1,n){ 39 if(del[i]<del[ans]) ans=i; 40 } 41 printf("%lld %lld\n",ans,del[ans]); 42 }
发现能A的和原来没有多大差别
我是沙雕
原文地址:https://www.cnblogs.com/monyhzc/p/12193651.html
时间: 2024-10-11 00:40:17