【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;
}