【Luogu P2323】[HNOI2006]公路修建问题

[HNOI2006]公路修建问题:

题目大意:

思路:

由于 \(c2\leq c1\),那我们只连 \(k\) 条一级边,其余都是二级。两遍生成树即可。

代码:

const int N = 1e4 + 10;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n, k, m;

struct edge
{
	int frm, to, nxt, val1, val2, id, grd;
}e[N << 2];
int head[N], tot;
void add(int u, int v, int val1, int val2, int id)
{
	e[++tot] = (edge){u, v, head[u], val1, val2, id}, head[u] = tot; 
}

bool cmp1 (edge a, edge b){return a.val1 < b.val1;}
bool cmp2 (edge a, edge b){return a.val2 < b.val2;}
bool cmp3 (edge a, edge b){return a.id < b.id;}

int fa[N];
int Find(int u) {return u == fa[u]? u: fa[u] = Find(fa[u]);} 
int ans;
vector <edge> Ans;

int main()
{
	n = Read(), k = Read(), m = Read();
	for (int i = 1; i < m; i++)
	{
		int u = Read(), v = Read(), val1 = Read(), val2 = Read();
		add (u, v, val1, val2, i);
	}
	sort (e + 1, e + 1 + tot, cmp1);
	
	for (int i = 1; i <= n; i++) fa[i] = i;
	int i;
	for (i = 1; i <= tot && k; i++)
	{
		int u = e[i].frm, v = e[i].to;
		u = Find(u), v = Find(v);
		if (u == v) continue;
		fa[u] = v; 
		ans = max(ans, e[i].val1);
		e[i].grd = 1; k--;
		Ans.push_back(e[i]);
	}
	
	sort (e + i, e + 1 + tot, cmp2);
	for (; i <= tot; i++)
	{
		int u = e[i].frm, v = e[i].to;
		u = Find(u), v = Find(v);
		if (u == v) continue;
		fa[u] = v; 
		ans = max(ans, e[i].val2);
		e[i].grd = 2;
		Ans.push_back(e[i]);
	}
	printf ("%d\n", ans);
	sort (Ans.begin(), Ans.end(), cmp3);
	for (int i = 0; i < Ans.size(); i++) printf ("%d %d\n", Ans[i].id, Ans[i].grd);
	return 0;
}
posted @ 2021-08-17 15:53  Jayun  阅读(31)  评论(0编辑  收藏  举报