zoukankan      html  css  js  c++  java
  • [BZOJ2654]tree

    [BZOJ2654]tree

    试题描述

    给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
    题目保证有解。

    输入

    第一行V,E,need分别表示点数,边数和需要的白色边数。
    接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。

    输出

    一行表示所求生成树的边权和。
    V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。

    输入示例

    2 2 1
    0 1 1 1
    0 1 2 0

    输出示例

    2

    数据规模及约定

    见“输入

    题解

    记得这道题是 WJMZBMR 神题。。。然而被我用类似“[BZOJ3624][Apio2008]免费道路”这道题的方法 rank 1 捉了。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 50010
    #define maxm 100010
    int n, m;
    struct Edge {
    	int u, v, w;
    	bool tp, has;
    	bool operator < (const Edge& t) const { return w < t.w; }
    } es[maxm];
    
    int fa[maxn];
    int findset(int x) { return x == fa[x] ? x : fa[x] = findset(fa[x]); }
    void init() {
    	for(int i = 1; i <= n; i++) fa[i] = i;
    	return ;
    }
    
    int main() {
    	n = read(); m = read(); int need = read();
    	for(int i = 1; i <= m; i++) {
    		int u = read() + 1, v = read() + 1, w = read(), tp = read();
    		es[i] = (Edge){ u, v, w, tp, 0 };
    	}
    	
    	sort(es + 1, es + m + 1);
    	init();
    	for(int i = 1; i <= m; i++) if(es[i].tp) {
    		int u = findset(es[i].u), v = findset(es[i].v);
    		if(u != v) fa[v] = u;
    	}
    	for(int i = 1; i <= m; i++) if(!es[i].tp) {
    		int u = findset(es[i].u), v = findset(es[i].v);
    		if(u != v) fa[v] = u, es[i].has = 1;
    	}
    	init();
    	int cnt = 0, ans = 0;
    	for(int i = 1; i <= m; i++) if(es[i].has)
    		fa[findset(es[i].v)] = findset(es[i].u), ans += es[i].w, cnt++;
    	for(int i = 1; i <= m && cnt < need; i++) if(!es[i].tp) {
    		int u = findset(es[i].u), v = findset(es[i].v);
    		if(u != v) fa[v] = u, ans += es[i].w, cnt++;
    	}
    	for(int i = 1; i <= m; i++) if(es[i].tp) {
    		int u = findset(es[i].u), v = findset(es[i].v);
    		if(u != v) fa[v] = u, ans += es[i].w;
    	}
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    

    然而最后又被 wzj 神犇用我的方法超过了。。。

  • 相关阅读:
    this 指向 及 调用方式
    页面布局上 左 右底部
    Thread Safety线程安全
    sql查删更
    LinuxMysql命令操作数据库
    excel链接sharepoint 用于 Excel 的 Microsoft Power Query
    W7无法更新
    发票点数计算
    sharepoint OWA问题解决
    zend studio 做前端推荐安装的插件
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5688918.html
Copyright © 2011-2022 走看看