// // // // // // // // // // // // // //

关于最小生成树

前言:

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

现在还是懒得弄...

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

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"<<'\n'
#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"<<'\n'
#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;
}

posted @ 2021-01-03 22:22  Blank_space  阅读(50)  评论(0编辑  收藏  举报
// // // // // // //