[补档]藏宝图
藏寶圖
題目
codeforces472D加強(qiáng)版,原題傳送門:http://codeforces.com/problemset/problem/472/D 本題在原題基礎(chǔ)上加了一問,然而就是這一問把我搞炸了= = Czy爬上黑紅樹,到達(dá)了一個(gè)奇怪的地方…… Czy發(fā)現(xiàn)了一張奇怪的藏寶圖。圖上有n個(gè)點(diǎn),m條無(wú)向邊。已經(jīng)標(biāo)出了圖中兩兩之間距離dist。但是czy知道,只有當(dāng)圖剛好又是一顆樹的時(shí)候,這張藏寶圖才是真的。如果藏寶圖是真的,那么經(jīng)過(guò)點(diǎn)x的邊的邊權(quán)平均數(shù)最大的那個(gè)x是藏著寶物的地方。請(qǐng)計(jì)算這是不是真的藏寶圖,如果是真的藏寶之處在哪里。INPUT
輸入數(shù)據(jù)第一行一個(gè)數(shù)T,表示T組數(shù)據(jù)。 對(duì)于每組數(shù)據(jù),第一行一個(gè)n,表示藏寶圖上的點(diǎn)的個(gè)數(shù)。 接下來(lái)n行,每行n個(gè)數(shù),表示兩兩節(jié)點(diǎn)之間的距離。OUTPUT
輸出一行或兩行。第一行”Yes”或”No”,表示這是不是真的藏寶圖。 若是真的藏寶圖,第二行再輸出一個(gè)數(shù),表示哪個(gè)點(diǎn)是藏寶之處。SAMPLE
INPUT
2 3 0 7 9 7 0 2 9 2 0 3 0 2 7 2 0 9 7 9 0OUTPUT
Yes 1 Yes 3解題報(bào)告
考試時(shí)只打出了第一問,還是O(n3)的復(fù)雜度,自然爆了零= = 正解: 首先我們考慮第一問,我們有了每?jī)蓛牲c(diǎn)之間的距離,并想辦法用其判斷這個(gè)圖是否是一棵樹,我們想,在一棵樹中,每?jī)牲c(diǎn)之間路徑是唯一的,故路徑長(zhǎng)度即為路徑所經(jīng)過(guò)所有邊的長(zhǎng)度之和,那么我們利用所給距離建出最小生成樹,假如該圖為樹,那么最小生成樹即為本身,假如不是,那么兩點(diǎn)間距離一定會(huì)有變化,這些利用dfs什么的就可以做到了,順便還可以建成圖。 這里需要注意的是,kruskal會(huì)被卡,要用prim (人題目給你矩陣還強(qiáng)行用kruskal也是醉),雖然突然不會(huì)prim了- - 接下來(lái)是第二問,那就很簡(jiǎn)單了- -,建完圖,一求邊權(quán)平均數(shù)就可以了 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 typedef long long L; 6 inline L read(){ 7 L sum(0); 8 char ch(getchar()); 9 for(;ch<'0'||ch>'9';ch=getchar()); 10 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 11 return sum; 12 } 13 struct edge{ 14 L s,e,n; 15 L w; 16 }a[6001]; 17 L pre[2501],tot; 18 inline void insert(L s,L e,L w){ 19 a[++tot].s=s; 20 a[tot].e=e; 21 a[tot].w=w; 22 a[tot].n=pre[s]; 23 pre[s]=tot; 24 } 25 L T,n; 26 L dis[2501][2501],dis1[2501],dis2[2501][2501]; 27 L fa[2501]; 28 bool vis[2501]; 29 L degree[2501]; 30 double num[2501]; 31 inline void clear(){ 32 tot=0; 33 memset(pre,-1,sizeof(pre)); 34 memset(dis,0,sizeof(dis)); 35 memset(dis1,0x7f,sizeof(dis1)); 36 memset(dis2,0,sizeof(dis2)); 37 memset(fa,0,sizeof(fa)); 38 memset(vis,0,sizeof(vis)); 39 memset(degree,0,sizeof(degree)); 40 memset(num,0,sizeof(num)); 41 } 42 inline void prim(){ 43 dis1[1]=0; 44 for(L i=1;i<=n;i++){ 45 L k(0); 46 for(L j=1;j<=n;j++) 47 if(!vis[j]&&dis1[j]<dis1[k]) 48 k=j; 49 vis[k]=1; 50 for(L j=1;j<=n;j++) 51 if(!vis[j]&&dis[k][j]<dis1[j]) 52 dis1[j]=dis[k][j],fa[j]=k; 53 } 54 } 55 inline void build(){ 56 for(L i=2;i<=n;i++){ 57 insert(i,fa[i],dis1[i]); 58 insert(fa[i],i,dis1[i]); 59 degree[i]++,degree[fa[i]]++; 60 } 61 } 62 inline void dfs(L start,L now,L fa,L deep){ 63 for(L i=pre[now];i!=-1;i=a[i].n){ 64 L e(a[i].e); 65 if(e==fa) 66 continue; 67 dis2[start][e]=deep+a[i].w; 68 dfs(start,e,now,deep+a[i].w); 69 num[now]+=a[i].w; 70 num[e]+=a[i].w; 71 } 72 } 73 inline bool judge(){ 74 for(L i=1;i<=n;i++) 75 for(L j=1;j<=n;j++) 76 if(i!=j) 77 if(dis[i][j]!=dis2[i][j]&&dis2[i][j]>0) 78 return false; 79 return true; 80 } 81 int main(){ 82 // freopen("1.in","r",stdin); 83 // freopen("1.out","w",stdout); 84 T=read(); 85 while(T--){ 86 clear(); 87 n=read(); 88 for(L i=1;i<=n;i++){ 89 for(L j=1;j<=n;j++) 90 dis[i][j]=read(); 91 dis[i][i]=0x7fffffff; 92 } 93 if(n==1){ 94 puts("Yes"); 95 puts("1"); 96 continue; 97 } 98 prim(); 99 build(); 100 for(L i=1;i<=n;i++) 101 dfs(i,i,-1,0); 102 if(!judge()){ 103 puts("No"); 104 continue; 105 } 106 puts("Yes"); 107 double mx(0); 108 L ans(0); 109 for(L i=1;i<=n;i++){ 110 num[i]/=(double)degree[i]; 111 if(num[i]>mx) 112 mx=num[i],ans=i; 113 } 114 printf("%d\n",ans); 115 } 116 } View Code?
轉(zhuǎn)載于:https://www.cnblogs.com/hzoi-mafia/p/7277670.html
總結(jié)
- 上一篇: windows下sshfs挂载远程文件夹
- 下一篇: day17.Python中lambda表