2018-10-18雜題選講
阿新 • • 發佈:2018-12-16
2018-10-18 雜題選講
T1 Distance Sums
給出一顆帶標號的樹的每個點到其他點的距離之和(每條邊長為1,保證距離之和兩兩不同),還原這棵樹的形態,如果不能還原輸出-1 (n<=10^5) 原題
數值最小的點是樹的重心,將它作為根。從大到小列舉數值,對於每個列舉到的點可以知道其子樹的大小,從而知道其父親的數值為d[u]-(n-2*size[u]),還原樹後檢驗根節點數值。
#include<bits/stdc++.h> using namespace std; #define fatherdis fd long long ans=0,n,father[100010],size[100010],first[100010],nxt[200020],u[200020],v[200020],tot=0,tmp,fatherdis,pos,judge=0,j,root,depth[100010]={0}; struct csx { long long num,dis; }p[100010]; bool cmp(const csx a,const csx b) { if (a.dis<b.dis) return true; else return false; } void add(long long from,long long to) { tot++; nxt[tot]=first[from]; first[from]=tot; u[tot]=from; v[tot]=to; return; } void dfs(long long point) { long long k=first[point]; while (k!=-1) { long long to=v[k]; if (father[point]!=to) { depth[to]=depth[point]+1; dfs(to); } k=nxt[k]; } ans+=depth[point]; return; } int main() { memset(first,-1,sizeof(first)); scanf("%lld",&n); for (int i=1;i<=n;i++) { scanf("%lld",&tmp); size[i]=1; p[i].num=i; p[i].dis=tmp; } sort(p+1,p+n+1,cmp); root=p[1].num; for (int i=n;i>1;i--) { fd=p[i].dis-(n-2*size[p[i].num]); j=i-1; while (j>0&&p[j].dis!=fd) j--; if (!j) { judge=1; break; } father[p[i].num]=p[j].num; size[p[j].num]+=size[p[i].num]; add(p[j].num,p[i].num); add(p[i].num,p[j].num); } dfs(root); if (judge||ans!=p[1].dis) printf("-1"); else for (int i=1;i<=tot/2;i++) printf("%lld %lld\n",u[i*2],v[i*2]); return 0; }
T2 Sergey and Subway
給定一棵樹,將距離<=2的點連邊,所有邊權為1,求任意兩點最短距離之和(n<=10^5) 原題
對於任意兩點之間的距離,若原先距離為偶數則新距離是dis/2,若原距離是奇數,則新距離是dis/2+1。將樹黑白染色,對第二種答案對貢獻數量為白點數*黑點數。
#include<bits/stdc++.h> using namespace std; long long n,u[400040],v[400040],first[200020],nxt[400040],tot=0,size[200020],color[200020],father[200020]; long long black=0,white=0,dis=0,ans; void add(long long from,long long to) { tot++; nxt[tot]=first[from]; first[from]=tot; u[tot]=from; v[tot]=to; return; } void dfs(long long point) { size[point]=1; long long j=first[point]; while (j!=-1) { long long to=v[j]; if (father[point]!=to) { father[to]=point; color[to]=color[point]*(-1); dfs(to); size[point]+=size[to]; } j=nxt[j]; } return; } int main() { memset(first,-1,sizeof(first)); scanf("%lld",&n); for (long long i=1;i<n;i++) { long long x,y; scanf("%lld%lld",&x,&y); add(x,y); add(y,x); } color[1]=1; dfs(1); for (long long i=1;i<=n;i++) { if (color[i]==1) black++; else if (color[i]==-1) white++; } for (long long i=1;i<=tot/2;i++) { long long up=u[i*2],down=v[i*2]; if (father[up]==down) swap(up,down); dis+=size[down]*(n-size[down]); } ans=(dis+black*white)/2; printf("%lld",ans); return 0; }