日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NOIp 2014 #2 联合权值 Label:图论 !!!未AC

發(fā)布時(shí)間:2025/1/21 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NOIp 2014 #2 联合权值 Label:图论 !!!未AC 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目描述

無向連通圖G 有n 個(gè)點(diǎn),n - 1 條邊。點(diǎn)從1 到n 依次編號(hào),編號(hào)為 i 的點(diǎn)的權(quán)值為W i ,每條邊的長(zhǎng)度均為1 。圖上兩點(diǎn)( u , v ) 的距離定義為u 點(diǎn)到v 點(diǎn)的最短距離。對(duì)于圖G 上的點(diǎn)對(duì)( u, v) ,若它們的距離為2 ,則它們之間會(huì)產(chǎn)生Wu

×Wv 的聯(lián)合權(quán)值。

請(qǐng)問圖G 上所有可產(chǎn)生聯(lián)合權(quán)值的有序點(diǎn)對(duì)中,聯(lián)合權(quán)值最大的是多少?所有聯(lián)合權(quán)值之和是多少?

輸入輸出格式

輸入格式:

?

輸入文件名為link .in。

第一行包含1 個(gè)整數(shù)n 。

接下來n - 1 行,每行包含 2 個(gè)用空格隔開的正整數(shù)u 、v ,表示編號(hào)為 u 和編號(hào)為v 的點(diǎn)之間有邊相連。

最后1 行,包含 n 個(gè)正整數(shù),每?jī)蓚€(gè)正整數(shù)之間用一個(gè)空格隔開,其中第 i 個(gè)整數(shù)表示圖G 上編號(hào)為i 的點(diǎn)的權(quán)值為W i 。

?

輸出格式:

?

輸出文件名為link .out 。

輸出共1 行,包含2 個(gè)整數(shù),之間用一個(gè)空格隔開,依次為圖G 上聯(lián)合權(quán)值的最大值

和所有聯(lián)合權(quán)值之和。由于所有聯(lián)合權(quán)值之和可能很大,[b]輸出它時(shí)要對(duì)10007 取余。 [/b]

?

輸入輸出樣例

輸入樣例#1:
5 1 2 2 3 3 4 4 5 1 5 2 3 10 輸出樣例#1:
20 74

說明

?

本例輸入的圖如上所示,距離為2 的有序點(diǎn)對(duì)有( 1,3) 、( 2,4) 、( 3,1) 、( 3,5) 、( 4,2) 、( 5,3) 。

其聯(lián)合權(quán)值分別為2 、15、2 、20、15、20。其中最大的是20,總和為74。

【數(shù)據(jù)說明】

對(duì)于30% 的數(shù)據(jù),1 < n≤ 100 ;

對(duì)于60% 的數(shù)據(jù),1 < n≤ 2000;

?對(duì)于100%的數(shù)據(jù),1 < n≤ 200 , 000 ,0 < wi≤ 10, 000 。

代碼

1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<vector> 6 #include<map> 7 #define MAXN 500005 8 using namespace std; 9 10 struct cc{ 11 map<int,int> m; 12 }nod[MAXN]; 13 14 int ans,sum,N; 15 int vis[MAXN],w[MAXN]; 16 vector<int> G[MAXN]; 17 18 int cc(int x,int pre){ 19 if(pre!=-1){ 20 for(int i=0;i<G[pre].size();i++){ 21 int pre_pre=G[pre][i]; 22 if(pre_pre==x) continue; 23 if(nod[x].m.count(pre_pre)!=0) continue; 24 25 nod[pre_pre].m[x]=nod[x].m[pre_pre]=1; 26 ans=max(ans,(w[pre_pre]*w[x])%10007);//注意題目描述,此處不應(yīng)該取模 27 sum=(sum+w[pre_pre]*w[x]*2)%10007; 28 // cout<<w[pre_pre]*w[x]<<endl; 29 } 30 } 31 vis[x]=1; 32 // printf("%d %d %d \n",x,pre,pre_pre); 33 for(int i=0;i<G[x].size();i++){ 34 if(!vis[G[x][i]]) cc(G[x][i],x); 35 } 36 } 37 38 int main(){ 39 // freopen("link.in","r",stdin); 40 // freopen("link.out","w",stdout); 41 42 scanf("%d",&N); 43 for(int i=1;i<N;i++){ 44 int x,y; 45 scanf("%d%d",&x,&y); 46 G[x].push_back(y); 47 G[y].push_back(x); 48 } 49 for(int i=1;i<=N;i++) scanf("%d",&w[i]); 50 cc(1,-1); 51 printf("%d %d\n",ans,sum); 52 return 0; 53 } 30分,腦洞map 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<vector> 6 #include<map> 7 #define MAXN 500005 8 using namespace std; 9 10 int ans,sum,N; 11 int vis[MAXN],w[MAXN]; 12 vector<int> G[MAXN]; 13 14 int cc(int x,int pre){ 15 if(pre!=-1){ 16 for(int i=0;i<G[pre].size();i++){ 17 int pre_pre=G[pre][i]; 18 if(pre_pre==x) continue; 19 if(!vis[pre_pre]) continue; 20 21 ans=max(ans,w[pre_pre]*w[x]);//ans不用取模 22 sum=(sum+w[pre_pre]*w[x]*2)%10007; 23 } 24 } 25 vis[x]=1; 26 for(int i=0;i<G[x].size();i++){ 27 if(!vis[G[x][i]]) cc(G[x][i],x); 28 } 29 } 30 31 int main(){ 32 // freopen("link.in","r",stdin); 33 // freopen("link.out","w",stdout); 34 35 scanf("%d",&N); 36 for(int i=1;i<N;i++){ 37 int x,y; 38 scanf("%d%d",&x,&y); 39 G[x].push_back(y); 40 G[y].push_back(x); 41 } 42 for(int i=1;i<=N;i++) scanf("%d",&w[i]); 43 cc(1,-1); 44 printf("%d %d\n",ans,sum); 45 return 0; 46 } 60分,還是TLE,大霧 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<vector> 6 #define MAXN 500005 7 using namespace std; 8 9 int ans,sum,N; 10 int vis[MAXN],w[MAXN]; 11 vector<int> G[MAXN]; 12 13 int cc(int x){ 14 vis[x]=1; 15 if(G[x].size()>=2){ 16 for(int i=0;i<G[x].size();i++){ 17 for(int j=i+1;j<G[x].size();j++){ 18 int k=G[x][i],y=G[x][j]; 19 ans=max(ans,w[k]*w[y]); 20 sum=(sum+w[k]*w[y]*2)%10007; 21 } 22 } 23 } 24 // cout<<x<<endl; 25 for(int i=0;i<G[x].size();i++){ 26 if(!vis[G[x][i]]) cc(G[x][i]); 27 } 28 } 29 30 int main(){ 31 // freopen("link.in","r",stdin); 32 // freopen("link.out","w",stdout); 33 34 scanf("%d",&N); 35 for(int i=1;i<N;i++){ 36 int x,y; 37 scanf("%d%d",&x,&y); 38 G[x].push_back(y); 39 G[y].push_back(x); 40 } 41 for(int i=1;i<=N;i++) scanf("%d",&w[i]); 42 cc(1); 43 printf("%d %d\n",ans,sum); 44 return 0; 45 } 60分的另外一種寫法

?

?

題解://格式優(yōu)化 by Radiumlrb

一、審題
首先我們一看到圖就就知道圖論有關(guān),又因?yàn)橛衝個(gè)點(diǎn)和n-1條邊,不難看出是一個(gè)無環(huán)圖,這對(duì)題目的難度降低了很多。如果直接模擬的話肯定不行,會(huì)超時(shí),所以我們應(yīng)該換一種思維,及一個(gè)點(diǎn)周圍的節(jié)點(diǎn)兩兩都能產(chǎn)生聯(lián)合全值,
下面就來完善這一思想。

二、算法討論
①、公式推導(dǎo):
假如一個(gè)點(diǎn)x存在n個(gè)節(jié)點(diǎn),分別為x1,x2…xn.
節(jié)點(diǎn)最大值只需存下節(jié)點(diǎn)中最大值,每次再用當(dāng)前節(jié)點(diǎn)與最大節(jié)點(diǎn)相乘,在于max比較。
則關(guān)于x節(jié)點(diǎn)間的的聯(lián)合全值之和為:
x(x2+x3…+xn)+x2(x1+x3…+xn)+xn(x1+x2…+xn-1) ;經(jīng)整理可知就是每?jī)蓚€(gè)節(jié)點(diǎn)相乘,最后再成2即可;
化簡(jiǎn)為:
x1(x2+x3…+xn)+x2(x3+x4…+xn)+xn-2(xn-1+xn)+xn-1*xn
可理解為把每一個(gè)點(diǎn)和所有前面出現(xiàn)的的點(diǎn)之和相乘再相加最后乘2。

②、注意事項(xiàng):
1、因?yàn)閳D是沒有環(huán)的,所以一點(diǎn)到距離為二的點(diǎn)必定有且僅有一條,每一個(gè)點(diǎn)任意兩個(gè)節(jié)點(diǎn)必將經(jīng)過此點(diǎn),所以我們不必討論是否會(huì)重復(fù)。
2、因?yàn)閿?shù)據(jù)范圍很大,用鄰接矩陣會(huì)爆內(nèi)存,所以我們必須要用鄰接矩陣才行(注意要存雙向邊)。
3、求聯(lián)合權(quán)值之和時(shí)必須邊做邊對(duì)10007取模,不然會(huì)超出范圍。

三、算法實(shí)現(xiàn)
用一個(gè)二維數(shù)組a存邊,一維數(shù)組max1用來存該點(diǎn)節(jié)點(diǎn)中的最大值,大概就是這樣吧,剩下的變量就在代碼中一一解釋。

四、代碼展示

//Orz P黨大神

1 c,qz,dd:array[0..400000]of longint; 2 n,i,tot,x,y,max:longint; 3 //max存最大值,tot存聯(lián)合全值之和 4 procedure sb(x:longint); 5 var i,tot1,nn,ny,max1:longint; 6 begin 7 tot1:=0; nn:=dd[x]; max1:=0; 8 ny:=a[nn].y; 9 //循環(huán)列舉該點(diǎn)的所有節(jié)點(diǎn) tot1存前面出現(xiàn)的節(jié)點(diǎn)全值之和。 10 repeat 11 if max1*qz[ny]>max then max:=max1*qz[ny]; 12 if qz[ny]>max1 then max1:=qz[ny]; 13 tot:=(tot+tot1*(qz[ny]mod 10007))mod 10007; 14 tot1:=(tot1+qz[ny])mod 10007; 15 //要不斷對(duì)10007取模 16 nn:=c[nn]; 17 ny:=a[nn].y; 18 until nn=0; 19 end; 20 begin 21 read(n); 22 for i:=1 to n-1 do 23 begin 24 read(x,y); 25 a[i*2-1].x:=x;a[i*2-1].y:=y; 26 c[i*2-1]:=dd[x];dd[x]:=i*2-1; 27 //此處為雙向邊 dd數(shù)組用來把起點(diǎn)相同的邊綁定在一起 28 a[i*2].x:=y; a[i*2].y:=x; 29 c[i*2]:=dd[y];dd[y]:=i*2; 30 end; 31 for i:=1 to n do 32 read(qz[i]); 33 for i:=1 to n do 34 sb(i); 35 tot:=tot mod 10007; 36 write(max,' ',tot*2 mod 10007); 37 //注意最后答案要乘2 38 end.

?

五、最后的寄語:
其實(shí)本題還有更簡(jiǎn)單的做法,就是搜邊即可,沒必要枚舉每個(gè)點(diǎn),這個(gè)留給大家自己去想,我就不多講。

轉(zhuǎn)載于:https://www.cnblogs.com/radiumlrb/p/6012303.html

總結(jié)

以上是生活随笔為你收集整理的NOIp 2014 #2 联合权值 Label:图论 !!!未AC的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。