联合权值 NOIP2014 提高组 Day1 T2
codevs 3728 聯合權值
題目描述
無向連通圖G 有n 個點,n - 1 條邊。點從1 到n 依次編號,編號為 i 的點的權值為W i ,每條邊的長度均為1 。圖上兩點( u , v ) 的距離定義為u 點到v 點的最短距離。對于圖G 上的點對( u, v) ,若它們的距離為2 ,則它們之間會產生Wu
×Wv 的聯合權值。
請問圖G 上所有可產生聯合權值的有序點對中,聯合權值最大的是多少?所有聯合權值之和是多少?
輸入輸出格式
輸入格式:
輸入文件名為link .in。
第一行包含1 個整數n 。
接下來n - 1 行,每行包含 2 個用空格隔開的正整數u 、v ,表示編號為 u 和編號為v 的點之間有邊相連。
最后1 行,包含 n 個正整數,每兩個正整數之間用一個空格隔開,其中第 i 個整數表示圖G 上編號為i 的點的權值為W i 。
輸出格式:
輸出文件名為link .out 。
輸出共1 行,包含2 個整數,之間用一個空格隔開,依次為圖G 上聯合權值的最大值
和所有聯合權值之和。由于所有聯合權值之和可能很大,[b]輸出它時要對10007 取余。
輸入輸出樣例
輸入樣例 1:
5
1 2
2 3
3 4
4 5
1 5 2 3 10
輸出樣例 1:
20 74
思路:首先60應該是很好拿的,去找每個點相距為2的點算就是了。
100分的話我們可以考慮兩個距離為2得點可以看做一個點的兩個孩子的距離,而權值總和可以看做各個點的不同的兩個孩子的權值之積。
某個點的最大權值為其最大和次大孩子的權值之積,而權值之和和話我們可以考慮對于任意個數,兩兩相乘的乘積之和就等于這些數的和的平方減去平方的和。2*(u*v)=(u+v)^2-u^2-v^2。
60分代碼
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int maxn=400000+10; int mod=10007; struct cc{int from,to; }es[maxn]; int first[maxn],next[maxn]; int tot=0; void build(int ff,int tt) {es[++tot]=(cc){ff,tt};next[tot]=first[ff];first[ff]=tot; } int s[maxn]; int ans=0,sum=0; void dfs(int x,int now,int step) {if(step>=2){int v=s[x]*s[now];ans=max(ans,v);sum=((sum%mod)+(v%mod))%mod;return;}for(int i=first[now];i;i=next[i]){int u=es[i].to;if(u!=x){dfs(x,u,step+1); } } } int main() {int n;scanf("%d",&n);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);build(x,y);build(y,x);}for(int i=1;i<=n;i++){scanf("%d",&s[i]);}for(int i=1;i<=n;i++){dfs(i,i,0);}printf("%d %d",ans,sum);return 0; }100分題解:
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int maxn=400000+10; const int mod=10007; struct cc{int from,to; }es[maxn]; int first[maxn],next[maxn]; int tot=0; void build(int ff,int tt) {es[++tot]=(cc){ff,tt};next[tot]=first[ff];first[ff]=tot; } int s[maxn]; int main() {int n;scanf("%d",&n);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);build(x,y);build(y,x);}for(int i=1;i<=n;i++){scanf("%d",&s[i]);}int ans1=0,ans2=0;for(int i=1;i<=n;i++){int sum1=0,sum2=0,max1=0,max2=0;for(int j=first[i];j;j=next[j]){int u=es[j].to;sum1=((sum1%mod)+(s[u]%mod))%mod;sum2=(sum2+s[u]*s[u])%mod;if(s[u]>max1){max2=max1,max1=s[u];} else if(s[u]>max2){max2=s[u];}}ans1=max(ans1,max1*max2);ans2=(ans2+sum1*sum1-sum2+mod)%mod;}printf("%d %d",ans1,ans2);return 0; }轉載于:https://www.cnblogs.com/-feather/p/7779883.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的联合权值 NOIP2014 提高组 Day1 T2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)mysql帮助命令使用说明
- 下一篇: sql server取某个时间段内所有日