CF605B Lazy Student(题解)

· · 题解

Description.

Solution.

考虑倒着思考 Kruskal 算法。
按边权从小到大排序。
每次插入一条边。
如果是树边,那就新开节点。
否则在当前节点内任意连边。
这样构造,每次非树边插入都比当前两端小。
所以必然正确。

Coding.

//是啊……你就是那只鬼了……所以被你碰到以后,就轮到我变成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
    x=0;char c=getchar(),f=0;
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=1;
    for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    if(f) x=-x;
}/*}}}*/
struct node{int w,id,fr,tw;char fg;}a[100005];int n,m,l=2,r=3,id=1;
int main()
{
    read(n),read(m);for(int i=1;i<=m;i++) read(a[i].w),read(a[i].fg),a[i].id=i;
    sort(a+1,a+m+1,[](node a,node b){return a.w<b.w||(a.w==b.w&&a.fg>b.fg);});
    for(int i=1;i<=m;i++)
    {
        if(a[i].fg) {a[i].fr=1,a[i].tw=++id;continue;}
        if(r>id) return puts("-1"),0;
        a[i].fr=l++,a[i].tw=r;if(l==r) r++,l=2;
    }sort(a+1,a+m+1,[](node a,node b){return a.id<b.id;});
    for(int i=1;i<=m;i++) printf("%d %d\n",a[i].fr,a[i].tw);
    return 0;
}