OSDN Git Service

Update mst.md
authorpartychicken <44670668+partychicken@users.noreply.github.com>
Wed, 28 Aug 2019 07:20:55 +0000 (15:20 +0800)
committerGitHub <noreply@github.com>
Wed, 28 Aug 2019 07:20:55 +0000 (15:20 +0800)
add code

docs/graph/mst.md

index 3d2ab38..c42a557 100644 (file)
@@ -521,6 +521,172 @@ int main() {
 
 我们在 kruskal 重构树上找到 $x$ 到根的路径上权值 $\leq val$ 的最浅的节点。显然这就是所有满足条件的节点所在的子树的根节点。
 
+??? note "[「LOJ 137」最小瓶颈路 加强版](https://loj.ac/problem/137)"
+
+    ```
+    #include<bits/stdc++.h>
+
+    using namespace std;
+
+    const int MAX_VAL_RANGE = 280010;
+
+    int n,m,log2Values[MAX_VAL_RANGE + 1];
+
+    namespace TR
+    {
+        struct Edge
+        {
+            int to,nxt,val;
+        }e[400010];
+        int cnt,head[140010];
+
+        void addedge(int u,int v,int val=0)
+        {
+            e[++cnt]=(Edge){v,head[u],val};
+            head[u]=cnt;
+        }
+
+        int val[140010];
+        namespace LCA
+        {
+            int sec[280010],cnt;
+            int pos[140010];
+            int dpth[140010];
+
+            void dfs(int now,int fa)
+            {
+                dpth[now]=dpth[fa]+1;
+                sec[++cnt]=now;
+                pos[now]=cnt;
+
+                for(int i=head[now];i;i=e[i].nxt)
+                {
+                    if(fa!=e[i].to)
+                    {
+                        dfs(e[i].to,now); 
+                        sec[++cnt]=now;
+                    }
+                }
+            }
+
+            int dp[280010][20];
+            void init()
+            {
+                dfs(2*n-1,0);
+                for(int i=1;i<=4*n;i++)
+                {
+                    dp[i][0]=sec[i];
+                }
+                for(int j=1;j<=19;j++)
+                {
+                    for(int i=1;i+(1<<j)-1<=4*n;i++)
+                    {
+                        dp[i][j]=dpth[dp[i][j-1]]<dpth[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
+                    }
+                }
+            }
+
+            int lca(int x,int y)
+            {
+                int l=pos[x],r=pos[y];
+                if(l>r)
+                {
+                    swap(l,r);
+                }
+                int k=log2Values[r - l + 1];
+                return dpth[dp[l][k]]<dpth[dp[r-(1<<k)+1][k]]?dp[l][k]:dp[r-(1<<k)+1][k];
+            }
+        }
+    }
+
+    using TR::addedge;
+
+    namespace GR
+    {
+        struct Edge
+        {
+            int u,v,val;
+
+            bool operator<(const Edge &other)const
+            {
+                return val<other.val;
+            }
+        }e[100010];
+
+        int fa[140010];
+
+        int find(int x)
+        {
+            return fa[x]==0?x:fa[x]=find(fa[x]);
+        }
+
+        void kruskal()
+        {
+            int tot=0,cnt=n;
+            sort(e+1,e+m+1);
+            for(int i=1;i<=m;i++)
+            {
+                int fau=find(e[i].u),fav=find(e[i].v);
+                if(fau!=fav)
+                {
+                    cnt++;
+                    fa[fau]=fa[fav]=cnt;
+                    addedge(fau,cnt);
+                    addedge(cnt,fau);
+                    addedge(fav,cnt);
+                    addedge(cnt,fav);
+                    TR::val[cnt]=e[i].val;
+                    tot++;
+                }
+                if(tot==n-1)
+                {
+                    break;
+                }
+            }
+        }
+    }
+
+    int ans;
+    int A,B,C,P;
+    inline int rnd()
+    {
+        return A=(A*B+C)%P;
+    }
+
+    void initLog2()
+    {
+        for(int i = 2;i <= MAX_VAL_RANGE;i++) {
+            log2Values[i] = log2Values[i >> 1] + 1;
+        }
+    }
+
+    int main()
+    {
+        initLog2();
+        cin>>n>>m;
+        for(int i=1;i<=m;i++)
+        {
+            int u,v,val;
+            cin>>u>>v>>val;
+            GR::e[i]=(GR::Edge){u,v,val};
+        }
+        GR::kruskal();
+        TR::LCA::init();
+        int Q;
+        cin>>Q;
+        cin>>A>>B>>C>>P;
+
+        while(Q--)
+        {
+            int u=rnd()%n+1,v=rnd()%n+1;
+            ans+=TR::val[TR::LCA::lca(u,v)];
+            ans%=1000000007;
+        }
+        cout<<ans;
+        return 0;
+    }
+    ```
+
 ??? note "[NOI 2018 归程](https://www.luogu.org/problem/P4768)"
     首先预处理出来每一个点到根节点的最短路。
 
@@ -533,3 +699,6 @@ int main() {
     询问的根节点可以使用 kruskal 重构树上倍增的方式求出。
 
     时间复杂度 $O((n+m+Q) \log n)$
+    
+
+??? note "[「LOJ 137」最小瓶颈路 加强版](https://loj.ac/problem/137)"