• [ARC093E] Bichrome Spanning Tree


    [题目链接]

    https://atcoder.jp/contests/arc093/tasks/arc093_c

    [题解]

    一个重要的观察是 : 最多只会用一条不在忽略颜色求得的最小生成树上的边。

    首先不妨求出最小生成树 , 并计算其权值 (W) , 令 (delta = X - W)

    (delta < 0) , 则答案为 (0)

    否则不妨求出加入一条边后生成树权值比 (W) 小 , 等于 (W) , 大于 (W) 的边数 , 分别为 (c0 , c1 , c2)

    (delta = 0) , 说明要么原最小生成树就合法 , 要么满足有一条可替换的边 , 答案为 ((2 ^ {N - 1} - 2) cdot 2 ^ {M - N + 1} + 2 cdot (2 ^ {c1} - 1) cdot 2 ^ {c2})

    (delta > 0) , 说明最小生成树同色 , 且能找到一条可替换的边 , 答案为 (2 cdot 2 ^ {c2} cdot (2 ^ {c1} - 1))

    时间复杂度 : (O((N + M)logN))

    [代码]

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i , l , r) for (int i = (l); i < (r); ++i)
    
    typedef long long LL;
    
    const int MN = 2e5 + 5 , MM = 4e5 + 5 , mod = 1e9 + 7;
    
    struct Edg {
    	  int to; LL w; int nxt;
    } E[MM << 1];
    
    struct Edge {
    	  int u , v; LL w;
    } A[MM << 1];
    
    int N , M , dest , fa[MN] , two[MM] , tot , head[MN] , use[MN];
    LL X , mx;
    
    inline void add(int u , int v , LL w) {
    	  E[++tot] = (Edg) {v , w , head[u]}; head[u] = tot;
    	  E[++tot] = (Edg) {u , w , head[v]}; head[v] = tot;
    }
    inline void get(int u , int lst , LL mv) {
    	  if (u == dest) { mx = mv; return; }
    	  for (int i = head[u]; i; i = E[i].nxt) {
    	  	  int v = E[i].to; if (v == lst) continue;
    	  	  get(v , u , max(mv , E[i].w));
    		}
    }
    inline LL query(int u , int v) {
    	  dest = v;
    	  get(u , 0 , 0);
    	  return mx;
    }
    inline int find(int x) {
    	  return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    inline bool cmp(Edge a , Edge b) {
    	  return a.w < b.w;
    } 
    inline bool mg(int u , int v) {
    	  if (find(u) == find(v)) return false;
    	  fa[find(u)] = find(v); return true; 
    }
    
    int main() {
    		
    		scanf("%d%d%lld" , &N , &M , &X);
    		two[0] = 1;
    		for (int i = 1; i <= M; ++i) two[i] = 2ll * two[i - 1] % mod;
    		for (int i = 1; i <= M; ++i) scanf("%d%d%lld" , &A[i].u , &A[i].v , &A[i].w);
    		sort(A + 1 , A + 1 + M , cmp);
    		for (int i = 1; i <= N; ++i) fa[i] = i;
    		LL ans = 0;
    		for (int i = 1; i <= M; ++i) if (mg(A[i].u , A[i].v)) add(A[i].u , A[i].v , A[i].w) , ans += (LL) A[i].w , use[i] = 1;
    		int c0 = 0 , c1 = 0 , c2 = 0;
    		LL d = X - ans;
    		if (d < 0) {
    			  puts("0");
    			  return 0;
    		}
    		for (int i = 1; i <= M; ++i) if (!use[i]) {
    				int t = A[i].w - query(A[i].u , A[i].v);
    				if (t > d) ++c2;
    				else if (t == d) ++c1;
    				else ++c0;
    		}
    		if (d == 0) printf("%d
    " , (1ll * (two[N - 1] - 2 + mod) % mod * two[M - N + 1] % mod + 2ll * (1ll * (two[c1] - 1) * two[c2] % mod + mod) % mod) % mod);
    		else printf("%d
    " , (2ll * two[c2] % mod * ((two[c1] - 1) % mod + mod) % mod) % mod); 
    	  return 0;
    }
  • 相关阅读:
    版本回退
    时光机穿梭
    创建版本库
    安装Git
    Git简介
    Nexus私服安装
    eclipse中创建MAVEN-web项目
    AsyncTask的使用
    在子线程中更新UI,只能使用Handler
    使用VideoView播放视频
  • 原文地址:https://www.cnblogs.com/evenbao/p/14321212.html
Copyright © 2020-2023  润新知