题解 构树
输入中给定的边会形成一些连通块
枚举点对,若不在同一连通块中且连边后仍满足限制就连
复杂度 \(O(n^2)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int l[N], r[N];
namespace task1{
int dsu[N], tot;
pair<int, int> e[N];
map<pair<int, int>, bool> mp;
inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
void solve() {
for (int i=1; i<=n; ++i) dsu[i]=i;
for (int i=1; i<=n; ++i) {
if (mp.find({i, l[i]})==mp.end()) {
if (find(i)==find(l[i])) {puts("-1"); return ;}
e[++tot]={i, l[i]}, mp[{i, l[i]}]=mp[{l[i], i}]=1;
dsu[find(i)]=find(l[i]);
}
if (mp.find({i, r[i]})==mp.end()) {
if (find(i)==find(r[i])) {puts("-1"); return ;}
e[++tot]={i, r[i]}, mp[{i, r[i]}]=mp[{r[i], i}]=1;
dsu[find(i)]=find(r[i]);
}
}
for (int i=1; i<=n; ++i)
for (int j=l[i]; j<=r[i]; ++j)
if (find(i)!=find(j) && i>=l[j] && i<=r[j])
dsu[find(i)]=find(j), e[++tot]={i, j}, mp[{i, j}]=mp[{j, i}]=1;
int rot=find(1);
for (int i=1; i<=n; ++i) if (find(i)!=rot) {puts("-1"); return ;}
if (tot!=n-1) {puts("-1"); return ;}
for (int i=1; i<=tot; ++i) printf("%d %d\n", e[i].fir, e[i].sec);
}
}
signed main()
{
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
n=read();
for (int i=1; i<=n; ++i) {
l[i]=read(), r[i]=read();
if (max(l[i], r[i])>n || min(l[i], r[i])<1) {puts("-1"); return 0;}
}
task1::solve();
return 0;
}