[HDOJ 4896] Minimal Spanning Tree [最小生成树]
2014-08-01 19:13
309 查看
题目给出了一个图,每个点和他的前后5个点连边,边的权值是由一个公式计算得出的。求最小生成树的边权和。
我们观察公式,发现其有一个循环节,为54。就是说点i上的边的权值和点i+54上的边的权值是完全相同的。然后我们就可以把这个图缩成5+54+54+53+5这么多个点的图,求最小生成树了。
左右的5是因为这5个点和其他点不同,其左右不是都有5条边。第一个54为添加不需重复的边准备,即可能有一些边是不需要和循环节一起重复很多次的。第二个54为循环节的54。后边的53为剩余的53,即总点数减去10然后模54的余数。
然后就是求最小生成树,对边排序后按序添加。如果两条边权值一样,那么将不是循环节的那条(即不会被复制多次的)放在前边,求最小生成树之后计算结果的时候,要将是循环节的边乘以循环节的个数,即拷贝多份。
标准解法不是这样..是DP+矩阵加速...现在这个解法我没有严格的证明..不过感觉上是对的,并且也A了...
我们观察公式,发现其有一个循环节,为54。就是说点i上的边的权值和点i+54上的边的权值是完全相同的。然后我们就可以把这个图缩成5+54+54+53+5这么多个点的图,求最小生成树了。
左右的5是因为这5个点和其他点不同,其左右不是都有5条边。第一个54为添加不需重复的边准备,即可能有一些边是不需要和循环节一起重复很多次的。第二个54为循环节的54。后边的53为剩余的53,即总点数减去10然后模54的余数。
然后就是求最小生成树,对边排序后按序添加。如果两条边权值一样,那么将不是循环节的那条(即不会被复制多次的)放在前边,求最小生成树之后计算结果的时候,要将是循环节的边乘以循环节的个数,即拷贝多份。
标准解法不是这样..是DP+矩阵加速...现在这个解法我没有严格的证明..不过感觉上是对的,并且也A了...
#include <cstdio> #include <algorithm> #include <iostream> using namespace std; const int mod=2333333; const int XX=5; inline bool notin(int i) { if (i<=XX+54||i>XX+54+54) return true; return false; } struct Edge { int x,y; long long v; void clear(int xx,int yy,long long vv) { x=xx;y=yy;v=vv; } friend bool operator < (const Edge &a,const Edge &b) { if (a.v!=b.v) return a.v<b.v; if (notin(a.x)) return true; return false; } }; struct DisjoinSet { int a[600]; void clear(int n) { for (int i=1;i<=n;i++) a[i]=i; } int get(int i) { if (a[i]==i) return i; return a[i]=get(a[i]); } void tosame(int x,int y) { x=get(x); y=get(y); a[x]=y; } }; DisjoinSet c; Edge b[1000]; int bp,n,pp; long long ans; int main() { int i,j,seed; while (scanf("%d%d",&n,&seed)!=EOF) { pp=1; while (n-54>=54+54+XX+XX) { n-=54; pp++; } c.clear(n); bp=0; long long x=seed; for (i=2;i<=n;i++) { x=x*907%mod; long long t=x; for (j=max(1,i-5);j<i;j++) { x=x*907%mod; long long w=t^x; b[bp++].clear(i,j,w); } } sort(b,b+bp); ans=0; for (i=0;i<bp;i++) { if (c.get(b[i].x)!=c.get(b[i].y)) { c.tosame(b[i].x,b[i].y); if (notin(b[i].x)) ans+=b[i].v; else ans+=b[i].v*pp; } } printf("%lld\n",ans); } return 0; }
相关文章推荐
- 最小生成树(Minimal Spanning Tree MST)--《算法导论》
- hdoj 4408 Minimum Spanning Tree 求最小生成树的数目
- hdu1162 Eddy's picture(图论:最小生成树-minimal spanning tree)
- UVALive 3662 Another Minimum Spanning Tree 曼哈顿最小生成树
- HDOJ 题目2682 Tree(最小生成树)
- 数据结构与算法分析–Minimum Spanning Tree(最小生成树)
- Geeks : Kruskal’s Minimum Spanning Tree Algorithm 最小生成树
- 最小生成树(MST,minimum spanning tree)
- Union Find 在 最小生成树(Minimum Spanning Tree)中的实现
- [hdu 4896]14多校J题 Minimal Spanning Tree 打表
- 说说最小生成树(Minimum Spanning Tree)
- 最小生成树 (Minimum Spanning Tree,MST) --- Kruskal算法
- Minimum spanning tree for each edge CodeForces - 609E(ST算法+树链剖分(或倍增LCA)+最小生成树)
- 5.4.1 最小生成树(Minimum-Spanning-Tree,MST)
- HDU 2489 Minimal Ratio Tree(图论-最小生成树)
- HDU 2489 Minimal Ratio Tree(最小生成树)
- HDU 4263 Red/Blue Spanning Tree【最小生成树原理】
- 说说最小生成树(Minimum Spanning Tree)
- HDU 2489 Minimal Ratio Tree(DFS+Kruskal最小生成树)
- 分布式系统下的最小生成树算法(Distributed Minimum Spanning Tree)