大意:
问能否确定1-n的一个排列满足所有条件
思路:
按题意确定每一个点和每一个位置对应的范围大小,如果能够找到一个满足条件的排列,也就意味着点与位置的约束不会互相矛盾,且能够一一匹配,所以跑一个匈牙利就可以了。
(其实赛时也有想过这个,但是经验太少,还是不知道怎么建图。。。)
确定numr,numl数组,表示每一个数字能放置的最远和最近的区间
再确定qr,ql数组,表示每一个位置能放的最大的数和最小的数
然后按关系建边即可
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=300;
ll numl[N],numr[N],ql[N],qr[N];
ll n,m;
ll op,l,r,a;
vector<ll> vt[310];
ll ans=0;
ll dfn[N];
ll ti=0;//时间戳
ll match[N];
bool dfs(ll u,ll tim)
{
for(ll y:vt[u])
{
if(dfn[y]==tim) continue;
dfn[y]=tim;
if(!match[y]||dfs(match[y],tim))
{
match[y]=u;
return 1;
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;++i)
{
numl[i]=ql[i]=1;
numr[i]=qr[i]=n;
}
for(int i=1;i<=m;++i)
{
cin>>op>>l>>r>>a;
numl[a]=max(numl[a],l);
numr[a]=min(numr[a],r);
for(int j=l;j<=r;++j)
{
if(op==1) qr[j]=min(qr[j],a);
else ql[j]=max(ql[j],a);
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
if(numl[i]<=j&&numr[i]>=j&&ql[j]<=i&&qr[j]>=i) vt[i].push_back(j);
}
}
for(int i=1;i<=n;++i)
{
if(dfs(i,++ti)) ans++;
}
if(ans!=n)
{
cout<<-1<<endl;
return 0;
}
for(int i=1;i<=n;++i) cout<<match[i]<<" ";
return 0;
}