• 关于最小生成树


    前言:

    由于太懒了 所以做完之后一直没弄

    现在还是懒得弄...

    把代码粘过来 题目的话 下次吧...(也可能就没有下次了

    1. 黑暗城堡

    /*
      Time: 12.30
      Worker: Blank_space
      Source: #10064. 「一本通 3.1 例 1」黑暗城堡
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define int long long
    #define void inline void
    #define ull unsigned long long
    #define Orz cout<<"ZXS AK IOI"<<'
    '
    #define emm(x) memset(x,0,sizeof x)
    #define emmm(x) memset(x,0x3f,sizeof x)
    using namespace std;
    /*--------------------------------------头文件*/
    const int A = 1e4 + 7;
    const int B = 1e5 + 7;
    const int C = 1e6 + 7;
    const int D = 1e7 + 7;
    const int mod = 2147483647;
    const int INF = 0x3f3f3f3f;
    /*------------------------------------常量定义*/
    int n, m, dis[1010], maxdep, ans = 1, sum[1010];
    bool vis[1010];
    struct edge {
    	int v, w, nxt;
    }e[C << 1];
    int head[1010], js;
    struct node {
    	int u, d;
    	bool operator < (const node & x) const
    	{
    		return d < x.d;
    	}
    };
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    void add_edge(int u, int v, int w)
    {
    	e[++js].v = v;
    	e[js].w = w;
    	e[js].nxt = head[u];
    	head[u] = js;
    }
    void scan()
    {
        n = read(); m = read();
        for(int i = 1; i <= m; i++)
        {
        	int x = read(), y = read(), z = read();
        	add_edge(x, y, z); add_edge(y, x, z);
        }
    }
    void dijk(int s)
    {
    	queue <node> q;
    	q.push((node){s, 0});
    	emmm(dis); dis[s] = 0;
    	while(!q.empty())
    	{
    		node t = q.front(); q.pop();
    		int u = t.u;
    		for(int i = head[u]; i; i = e[i].nxt)
    		{
    			int v = e[i].v, w = e[i].w;
    			if(dis[v] > dis[u] + w)
    			{
    				dis[v] = dis[u] + w;
    				q.push((node){v, dis[v]});
    			}
    		}
    	}
    }
    void add()
    {
    	for(int u = 1; u <= n; u++)
    		for(int i = head[u]; i; i = e[i].nxt)
    			if(dis[e[i].v] == dis[u] + e[i].w) sum[e[i].v]++;
    }
    void print()
    {
    	for(int i = 1; i <= n; i++)
    		if(sum[i]) ans = ans * sum[i] % mod;
    	printf("%lld", ans);
    }
    /*----------------------------------------函数*/
    signed main()
    {
    //  freopen(".in","r",stdin);
    //  freopen(".out","w",stdout);
    
    	scan();
        dijk(1);
        add();
        print();
        
    //  fclose(stdin);
    //  fclose(stdout);
    	return 0;
    }
    
    

    2. 北极通讯网络

    不会(简洁 明了)

    3. 新的开始

    /*
      Time: 1.2
      Worker: Blank_space
      Source: #10066. 「一本通 3.1 练习 1」新的开始
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    /*--------------------------------------头文件*/
    const int A = 1e4 + 7;
    const int B = 1e5 + 7;
    const int C = 1e6 + 7;
    const int D = 1e7 + 7;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const int FFF = 0x8fffffff;
    /*------------------------------------常量定义*/
    int n, a[310], fa[310], ans, cnt;
    struct edge {
    	int u, v, w, nxt;
    	bool operator < (const edge & x) const {return w < x.w;}
    }e[C];
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
    /*----------------------------------------函数*/
    int main()
    {
        n = read(); 
        for(int i = 1; i <= n; i++) a[i] = read(), fa[i] = i;
        for(int i = 1; i <= n; i++)
        {
        	for(int j = 1; j <= n; j++)
        	{
        		int x = read();
        		if(i == j) continue;
        		e[++cnt].u = i; e[cnt].v = j; e[cnt].w = x;
        	}
        	e[++cnt].u = i; e[cnt].v = n + 1; e[cnt].w = a[i];
        	e[++cnt].u = n + 1; e[cnt].v = i; e[cnt].w = a[i];
        }
        fa[n + 1] = n + 1; sort(e + 1, e + 1 + cnt);
        for(int i = 1; i <= cnt; i++)
        {
        	int u = e[i].u, v = e[i].v, w = e[i].w;
        	int x = find(u), y = find(v);
        	if(x == y) continue;
        	fa[y] = x; ans += w;
        }
        printf("%d", ans);	
    	return 0;
    }
    
    

    4. 构造完全图

    /*
      Time: 1.2
      Worker: Blank_space
      Source: #10067. 「一本通 3.1 练习 2」构造完全图
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #include<algorithm>
    #define int long long
    using namespace std;
    /*--------------------------------------头文件*/
    const int A = 1e4 + 7;
    const int B = 1e5 + 7;
    const int C = 1e6 + 7;
    const int D = 1e7 + 7;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const int FFF = 0x8fffffff;
    /*------------------------------------常量定义*/
    int n, fa[B], cnt, num[B], ans;
    struct edge {
    	bool operator < (const edge & x) const {return w < x.w;}
    	int u, v, w;
    }e[B << 1];
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
    /*----------------------------------------函数*/
    signed main()
    {
        n = read();
        for(int i = 1; i <  n; i++)
        {
        	int x = read(), y = read(), z = read();
        	e[++cnt].u = x; e[cnt].v = y; e[cnt].w = z;
        	e[++cnt].u = y; e[cnt].v = x; e[cnt].w = z;
    		fa[i] = i; num[i] = 1;
        }
        fa[n] = n; num[n] = 1;
        sort(e + 1, e + 1 + cnt);
    	for(int i = 1; i <= cnt; i++)
    	{
    		int u = e[i].u, v = e[i].v, w = e[i].w;
    		int x = find(u), y = find(v);
    		if(x == y) continue;
    		ans += (num[x] * num[y] - 1) * (w + 1) + w;
    		fa[y] = x; num[x] += num[y];
    	}
    	printf("%lld", ans);
    	return 0;
    }
    

    5. 秘密的牛奶运输

    /*
      Time: 1.2
      Worker: Blank_space
      Source: #10068. 「一本通 3.1 练习 3」秘密的牛奶运输
      严格次小生成树
      先把最小生成树跑出来 再枚举每一条非树边 找链接这两点的路径上的最大边进行替换
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #include<algorithm>
    #define int long long
    using namespace std;
    /*--------------------------------------头文件*/
    const int A = 1e4 + 7;
    const int B = 1e5 + 7;
    const int C = 1e6 + 7;
    const int D = 1e7 + 7;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const int FFF = 0x8fffffff;
    /*------------------------------------常量定义*/
    int n, m, _ans = 1e10, d[510], dfn[510], pos[510], top[510], dep[510], siz[510], son[510], fa[510], cnt, sum, f[510];
    struct edge {
    	int u, v, w, nxt;
    	bool t;
    	bool operator < (const edge & x) const {return w < x.w;}
    }e[B], a[B];
    int head[510], js;
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int find(int x) {return x == f[x] ? x : f[x] = find(f[x]);}
    void add_edge(int u, int v, int w)
    {
    	e[++js].u = u;
    	e[js].v = v;
    	e[js].w = w;
    	e[js].nxt = head[u];
    	head[u] = js;
    }
    namespace seg {
    	#define ls(x) x << 1
    	#define rs(x) x << 1 | 1
    	struct node {
    		int l, r, mid, maxx, cmax;
    	}t[B << 2];
    	void push_up(int p)
    	{
    		t[p].maxx = max(t[ls(p)].maxx, t[rs(p)].maxx);
    		t[p].cmax = max(t[p].maxx == t[ls(p)].maxx ? t[ls(p)].cmax : t[ls(p)].maxx, t[p].maxx == t[rs(p)].maxx ? t[rs(p)].cmax : t[rs(p)].maxx);	
    	}
    	void build(int p, int l, int r)
    	{
    		t[p].l = l; t[p].r = r; t[p].mid = (l + r) >> 1;
    		if(l == r) {t[p].maxx = d[pos[l]]; t[p].cmax = -1; return ;}
    		build(ls(p), l, t[p].mid); build(rs(p), t[p].mid + 1, r);
    		push_up(p);
    	}
    	node query(int p, int l, int r)
    	{
    		if(l <= t[p].l && t[p].r <= r) return t[p];
    		node res1, res2, res3;
    		res1.maxx = res1.cmax = res2.maxx = res2.cmax = res3.maxx = res3.cmax = 0;
    		if(l <= t[p].mid) res1 = query(ls(p), l, r);
    		if(r > t[p].mid) res2 = query(rs(p), l, r);
    		res3.maxx = max(res1.maxx, res2.maxx);
    		res3.cmax = max(res3.maxx == res1.maxx ? res1.cmax : res1.maxx, res3.maxx == res2.maxx ? res2.cmax : res2.maxx);
    		return res3;
    	}
    }
    namespace cut {
    	void dfs(int u, int pre)
    	{
    		fa[u] = pre; dep[u] = dep[pre] + 1; siz[u] = 1; 
    		for(int i = head[u]; i; i = e[i].nxt)
    		{
    			int v = e[i].v, w = e[i].w;
    			if(v == pre) continue; d[v] = w;
    			dfs(v, u); siz[u] += siz[v];
    			if(!son[u] || siz[son[u]] < siz[v]) son[u] = v;
    		}
    	}
    	void dfs2(int u, int tp)
    	{
    		dfn[u] = ++cnt; pos[cnt] = u; top[u] = tp;
    		if(!son[u]) return ; dfs2(son[u], tp);
    		for(int i = head[u]; i; i = e[i].nxt)
    		{
    			int v = e[i].v;
    			if(v == fa[u] || v == son[u]) continue;
    			dfs2(v, v);
    		}
    	}
    	int query(int x, int y, int z)
    	{
    		int ans = 0;
    		while(top[x] != top[y])
    		{
    			if(dep[top[x]] < dep[top[y]]) swap(x, y);
    			seg::node res = seg::query(1, dfn[top[x]], dfn[x]);
    			ans = max(ans, res.maxx == z ? res.cmax : res.maxx);
    			x = fa[top[x]];
    		}
    		if(x == y) return ans;
    		if(dfn[x] > dfn[y]) swap(x, y);
    		seg::node res = seg::query(1, dfn[x] + 1, dfn[y]);
    		ans = max(ans, res.maxx == z ? res.cmax : res.maxx);
    		return ans;
    	}
    }
    /*----------------------------------------函数*/
    signed main()
    {
        n = read(); m = read();
        for(int i = 1; i <= n; i++) f[i] = i;
        for(int i = 1; i <= m; i++) a[i].u = read(), a[i].v = read(), a[i].w = read();
        sort(a + 1, a + 1 + m);
        for(int i = 1; i <= m; i++)
        {
        	int u = a[i].u, v = a[i].v, w = a[i].w;
        	int x = find(u), y = find(v);
        	if(x == y) continue; a[i].t = 1; sum += w;
        	f[y] = x; add_edge(u, v, w); add_edge(v, u, w);
        }
        cut::dfs(1, 0); cut::dfs2(1, 1); seg::build(1, 1, cnt);
        for(int i = 1; i <= m; i++)
        {
        	if(a[i].t) continue;
        	int u = a[i].u, v = a[i].v, w = a[i].w;
        	int res = cut::query(u, v, w);
        	_ans = min(_ans, w - res);
        }
        printf("%lld", _ans + sum);
    	return 0;
    }
    
    

    6. Tree

    /*
      Time: 1.2
      Worker: Blank_space
      Source: #10069. 「一本通 3.1 练习 4」Tree
      黑白边分开选 白边优先
      
      然而并不对
      二分加权最小生成树  二分一个权值 加到白边上 排序 跑最小生成树
       
      仍旧过不了 二分挂掉了
      
      一段时间的修码...
      
      二分并没有问题  挂掉的是排序
      当权值相等时按照白点在前的顺序排  AC 
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    /*--------------------------------------头文件*/
    const int A = 1e4 + 7;
    const int B = 1e5 + 7;
    const int C = 1e6 + 7;
    const int D = 1e7 + 7;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const int FFF = 0x8fffffff;
    /*------------------------------------常量定义*/
    int n, m, ned, cnt, fa[B], ans, sum, maxx, _ans;
    struct edge {
    	int u, v, w, nxt;
    	bool p;
    	bool operator < (const edge & x) const {return w == x.w ? p > x.p : w < x.w;}
    }e[B << 1];
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
    int kruskal()
    {
    	int sum = 0; ans = 0;
    	sort(e + 1, e + 1 + m);
        for(int i = 1; i <= n; i++) fa[i] = i;
    	for(int i = 1; i <= m; i++)
    	{
    		int u = e[i].u, v = e[i].v, w = e[i].w;
    		int x = find(u), y = find(v);
    		if(x == y) continue; ans += w;
    		fa[y] = x; if(e[i].p) sum++;
    	}
    	return sum;
    }
    bool check(int x)
    {
    	for(int i = 1; i <= m; i++) if(e[i].p) e[i].w += x;
    	int num = kruskal();
    	for(int i = 1; i <= m; i++) if(e[i].p) e[i].w -= x;
    	return num >= ned;
    }
    /*----------------------------------------函数*/
    int main()
    {
    //	freopen("tree20.in", "r", stdin);
        n = read(); m = read(); ned = read();
        for(int i = 1; i <= m; i++)
        {
        	int x = read() + 1, y = read() + 1, z = read(), o = read();
        	e[i].u = x; e[i].v = y; e[i].w = z; e[i].p = o ^ 1;
        }
        int l = -105, r = 105;
        while(l <= r)
        {
        	int mid = (l + r) >> 1;
        	if(check(mid)) _ans = mid, l = mid + 1;
        	else r = mid - 1;
        }
        check(_ans);
        ans -= ned * _ans;
        printf("%d", ans);
    	return 0;
    }	
    

    7. 最小生成树计数

    /*
      Time: 1.2
      Worker: Blank_space
      Source: #10070. 「一本通 3.1 练习 5」最小生成树计数
      不同的树一定是以权值相等的非树边替换了树边 直接递归找相等的边
      发现不太好实现  且最终答案难以统计
      参照题解 
      每种权值的边使用数量确定 深搜判断 
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    /*--------------------------------------头文件*/
    const int A = 1e4 + 7;
    const int B = 1e5 + 7;
    const int C = 1e6 + 7;
    const int D = 1e7 + 7;
    const int mod = 31011;
    const int INF = 0x3f3f3f3f;
    const int FFF = 0x8fffffff;
    /*------------------------------------常量定义*/
    int n, m, sum, ans = 1, fa[110], cnt, tot;
    struct edge {
    	int u, v, w, nxt;
    	bool p;
    	bool operator < (const edge & x) const {return w < x.w;}
    }e[A], c[A];
    int head[110], js;
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int find(int x) {return x == fa[x] ? x : find(fa[x]);} 
    void dfs(int t, int i, int num)
    {
    	if(i == c[t].v + 1) {if(num == c[t].w) sum++; return ;}
    	int u = e[i].u, v = e[i].v;
    	int x = find(u), y = find(v);
    	if(x != y) {fa[y] = x; dfs(t, i + 1, num + 1); fa[x] = x; fa[y] = y;}
    	dfs(t, i + 1, num);
    }
    /*----------------------------------------函数*/
    int main()
    {
        n = read(); m = read();
        for(int i = 1; i <= n; i++) fa[i] = i;
        for(int i = 1; i <= m; i++)
    		e[i].u = read(), e[i].v = read(), e[i].w = read();
        sort(e + 1, e + 1 + m);
        for(int i = 1; i <= m; i++)
        {
        	int u = e[i].u, v = e[i].v, w = e[i].w;
        	if(w != e[i - 1].w) {c[cnt].v = i - 1; c[++cnt].u = i;}
        	int x = find(u), y = find(v);
        	if(x == y) continue;
        	fa[y] = x; c[cnt].w++; tot++;
        }
        c[cnt].v = m; if(tot != n - 1) {puts("0"); return 0;}
        for(int i = 1; i <= n; i++) fa[i] = i;
        for(int i = 1; i <= cnt; i++)
        {
        	sum = 0;
        	dfs(i, c[i].u, 0);
        	ans = ans * sum % mod;
        	for(int j = c[i].u; j <= c[i].v; j++)
        	{
        		int x = find(e[j].u), y = find(e[j].v);
        		if(x == y) continue; fa[y] = x;
        	}
        }
        printf("%d", ans);
    	return 0;
    }
    
    

    8. 次小生成树

    /*
      Time: 12.30
      Worker: Blank_space
      Source: P4180 严格次小生成树
      先跑出最小生成树  枚举非树边  考虑加边删边
      维护最大值与严格次大值  计算加边 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define ll long long
    #define void inline void
    #define ull unsigned long long
    #define Orz cout<<"ZXS AK IOI"<<'
    '
    #define emm(x) memset(x,0,sizeof x)
    #define emmm(x) memset(x,0x3f,sizeof x)
    using namespace std;
    /*--------------------------------------头文件*/
    const int A = 1e4 + 7;
    const int B = 1e5 + 7;
    const int C = 1e6 + 7;
    const int D = 1e7 + 7;
    const int mod = 1e9 + 7;
    const int INF = 1e16 + 7;
    /*------------------------------------常量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int n, m, fa[C], dep[C], top[C], siz[C], son[C], cnt, dfn[C], pos[C], f[C], _a[C], tot;
    ll _ans;
    struct edge {
    	int u, v, nxt;
    	ll w;
    //	bool operator < (const edge & x)const{return w == x.w ? u == x.u ? v < x.v : u < x.u : w < x.w;}
    }e[C << 1];
    int head[C], js;
    struct dg {
    	int x, y;
    	ll z;
    	bool p;
    	bool operator < (const dg & t) const {return z < t.z;}
    }a[C];
    /*------------------------------------变量定义*/
    int find(int x) {return x == f[x] ? x : f[x] = find(f[x]);}
    //bool cmp(edge x, edge y) {return x.w < y.w;}
    void add_edge(int u, int v, ll w)
    {
    	e[++js].u = u;
    	e[js].v = v;
    	e[js].w = w;
    	e[js].nxt = head[u];
    	head[u] = js;
    }
    namespace seg {
    	#define ls(x) x << 1
    	#define rs(x) x << 1 | 1
    	struct node {
    		int l, r, mid;
    		ll max, cax;
    	}t[B << 2];
    	void push_up(int p)
    	{
    		t[p].max = max(t[ls(p)].max, t[rs(p)].max);
    		t[p].cax = max(t[p].max == t[ls(p)].max ? t[ls(p)].cax : t[ls(p)].max, t[p].max == t[rs(p)].max ? t[rs(p)].cax : t[rs(p)].max);
    	}
    	void build(int p, int l, int r)
    	{
    		t[p].l = l; t[p].r = r; t[p].mid = (l + r) >> 1;
    		if(l == r) {t[p].max = _a[pos[l]]; t[p].cax = -1; return ;}
    		build(ls(p), l, t[p].mid); build(rs(p), t[p].mid + 1, r);
    		push_up(p);
    	}
    	node query(int p, int l, int r)
    	{
    		if(l <= t[p].l && t[p].r <= r) return t[p];
    		node res1, res2, res3;
    		res1.max = res1.cax = res2.max = res2.cax = res3.max = res3.cax = 0;
    		if(l <= t[p].mid) res1 = query(ls(p), l, r);
    		if(r > t[p].mid) res2 = query(rs(p), l, r);
    		res3.max = max(res1.max, res2.max);
    		res3.cax = max(res3.max == res1.max ? res1.cax : res1.max, res3.max == res2.max ? res2.cax : res2.max);
    		return res3;
    	}
    }
    namespace cut {
    	void dfs(int u, int pre)
    	{
    		fa[u] = pre; dep[u] = dep[pre] + 1; siz[u] = 1;
    		for(int i = head[u]; i; i = e[i].nxt)
    		{
    			int v = e[i].v, w = e[i].w;
    			if(v == pre) continue; _a[v] = w;
    			dfs(v, u); siz[u] += siz[v];
    			if(!son[u] || siz[son[u]] < siz[v]) son[u] = v;
    		}
    	}
    	void dfs2(int u, int tp)
    	{
    		dfn[u] = ++cnt; pos[cnt] = u; top[u] = tp;
    		if(!son[u]) return ; dfs2(son[u], tp);
    		for(int i = head[u]; i; i = e[i].nxt)
    		{
    			int v = e[i].v;
    			if(v == fa[u] || v == son[u]) continue;
    			dfs2(v, v);
    		}
    	}
    	int query(int x, int y, int z)
    	{
    		ll ans = 0;
    		while(top[x] != top[y])
    		{
    			if(dep[top[x]] < dep[top[y]]) swap(x, y);
    			seg::node res = seg::query(1, dfn[top[x]], dfn[x]);
    			ans = max(ans, res.max == z ? res.cax : res.max);
    			x = fa[top[x]];
    		}
    		if(x == y) return ans;
    		if(dfn[x] > dfn[y]) swap(x, y);
    		seg::node res = seg::query(1, dfn[x] + 1, dfn[y]);
    		ans = max(ans, res.max == z ? res.cax : res.max);
    		return ans;
    	}
    }
    /*----------------------------------------函数*/
    signed main()
    {
    //  freopen("ex_tree1.in","r",stdin);
    //  freopen(".out","w",stdout);
    
    	freopen("milktrans2.in", "r", stdin);
        n = read(); m = read();
        for(int i = 1; i <= n; i++) f[i] = i;
        for(int i = 1; i <= m; i++) a[i].x = read(), a[i].y = read(), a[i].z = read();
        sort(a + 1, a + 1 + m);
        for(int i = 1; i <= m; i++)
        {
        	int u = a[i].x, v = a[i].y;
    		ll w = a[i].z;
        	int x = find(u), y = find(v);
        	if(x == y) continue;
        	f[y] = x; a[i].p = 1; _ans += w;
    		add_edge(u, v, w); add_edge(v, u, w);
        }
        cut::dfs(1, 0); cut::dfs2(1, 1); seg::build(1, 1, n);
        ll ans = INF;
        for(int i = 1; i <= m; i++)
        {
        	if(a[i].p) continue;
        	int u = a[i].x, v = a[i].y;
    		ll w = a[i].z;
        	ll res = cut::query(u, v, w);
        	ans = min(ans, w - res);
        }
        printf("%lld", ans + _ans);
        
    //  fclose(stdin);
    //  fclose(stdout);
    	return 0;
    }
    
    
  • 相关阅读:
    美剧字幕美国怪谭第一季第4集
    ios 中生成随机数
    美剧字幕绿箭侠第一季第1集
    关于iOS6应用中第三方类库不支持armv7s的问题解决
    美剧字幕美国怪谭第一季第2集
    美剧字幕美国怪谭第一季第一集
    美剧字幕美国怪谭第一季第3集
    NewWords/1100
    Developing for App StorePreparing the Development Team03
    平静(转载)
  • 原文地址:https://www.cnblogs.com/blank-space-/p/14227222.html
Copyright © 2020-2023  润新知