题目:
题目背景
SOURCE:NOIP2016-RZZ-1
题目描述
有 N 个城市,这些城市通过 M 条无向边互相连通,每条边有一个权值 Ci ,表示这条边的长度为 2^(Ci) ,没有两条边的长度是相同的。
设 d(i,j)为城市 i 到城市 j 的最短路长度,求:
答案以二进制输出。
输入格式
第一行,两个正整数 N ,M 。
接下来 M 行,每行三个正整数 Ai,Bi,Ci ,表示城市 Ai,Bi 间有一条权值为 Ci 的无向边。
输出格式
输出一个二进制数,表示所有无序点对间的最短路长度之和(即问题描述中的式子)。
样例数据 1
备注
【样例解释】
【数据规模与约定】
对于 30% 的数据,N,M≤50。
对于 60% 的数据,N,M≤100。
对于 80% 的数据,N≤2000;M≤10000。
对于 100% 的数据,1≤N≤105;1≤M≤2×105;1≤Ai,Bi≤N,Ai≠Bi,0≤Ci<M。
题解:
首先可以看出要选的边的集合为最小生成树(边互不相等且为2的x次方可以推出),然后dfs计算每条边左右两边对应的size然后计算这条边对答案的贡献
md忘记枚举边计算贡献这种操作了···
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; int cnt=0,father[200005]; long long ans[500000]; int n,m,first[200010],next[500010],go[500010],w[500010],size[500010],tot=0; inline int R() { int i=0,f=1;char c; for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar()); if(c=='-')c=getchar(),f=-1; for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f; } inline int getfather(int a) { if(father[a]==a) return a; father[a]=getfather(father[a]); return father[a]; } inline void combfa(int a,int b) { father[getfather(a)]=getfather(b); } struct node { int from,go,val; }edge[400005]; inline bool comp(node a,node b) { return a.val<b.val; } inline void comb(int a,int b,int c) { next[++tot]=first[a],first[a]=tot,go[tot]=b,w[tot]=c; next[++tot]=first[b],first[b]=tot,go[tot]=a,w[tot]=c; } inline void dfs(int u,int fa) { size[u]=1; for(int e=first[u],v;e;e=next[e]) { v=go[e]; if(v==fa) continue; dfs(v,u); size[u]+=size[v]; ans[w[e]]+=(long long)size[v]*(n-size[v]); cnt=max(cnt,w[e]); } } void work() { for(int i=0;i<=cnt;i++) if(ans[i]>1)ans[i+1]+=ans[i]/2,ans[i]%=2; int tmp=cnt+1; while(ans[tmp]>1)ans[tmp+1]+=ans[tmp]/2,ans[tmp++]%=2; cnt=tmp; for(int i=cnt;i>=0;i--) cout<<ans[i]; } int main() { //freopen("roads.in","r",stdin); //freopen("roads.out","w",stdout); n=R(),m=R(); int a,b,c; for(int i=1;i<=n;i++) father[i]=i; for(int i=1;i<=m;i++) { a=R(); b=R(); c=R(); edge[i].from=a; edge[i].go=b; edge[i].val=c; } sort(edge+1,edge+m+1,comp); int cntt=0; for(int i=1;i<=m;i++) { if(getfather(edge[i].from)!=getfather(edge[i].go)) { combfa(edge[i].from,edge[i].go); cntt++; comb(edge[i].from,edge[i].go,edge[i].val); } if(cntt==n-1) break; } dfs(1,0); work(); return 0; }