二分图最大匹配,枚举。
可以计算出每一个位置可以放哪些数字,每个数字可以放在哪些位置,这样就可以建二分图了。
如果二分图最大匹配不到$n$,则无解。否则构造字典序最小的解,可以枚举每一位放什么数字,然后再判断是否有解。
#include<bits/stdc++.h> using namespace std; const int maxn=100+10; int n,m1,m2; int pL[60],pR[60],nL[60],nR[60]; int f,ans[60],cun[60],u[60][60]; const int INF = 0x7FFFFFFF; struct Edge { int from, to, cap, flow; Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){} }; vector<Edge>edges; vector<int>G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn]; int s, t; void init() { for (int i = 0; i < maxn; i++) G[i].clear(); edges.clear(); } void Addedge(int from, int to, int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0)); int w = edges.size(); G[from].push_back(w - 2); G[to].push_back(w - 1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int>Q; Q.push(s); d[s] = 0; vis[s] = 1; while (!Q.empty()) { int x = Q.front(); Q.pop(); for (int i = 0; i<G[x].size(); i++) { Edge e = edges[G[x][i]]; if (!vis[e.to] && e.cap>e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if (x == t || a == 0) return a; int flow = 0, f; for (int &i = cur[x]; i<G[x].size(); i++) { Edge e = edges[G[x][i]]; if (d[x]+1 == d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0) { edges[G[x][i]].flow+=f; edges[G[x][i] ^ 1].flow-=f; flow+=f; a-=f; if(a==0) break; } } if(!flow) d[x] = -1; return flow; } int dinic(int s, int t) { int flow = 0; while (BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; } int main() { while(~scanf("%d%d%d",&n,&m1,&m2)) { f=0; memset(u,0,sizeof u); for(int i=1;i<=n;i++) nL[i]=pL[i]=1,nR[i]=pR[i]=n; for(int i=1;i<=m1;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); for(int j=a;j<=b;j++) pL[j]=max(c,pL[j]); nL[c] = max(nL[c],a); nR[c] = min(nR[c],b); } for(int i=1;i<=m2;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); for(int j=a;j<=b;j++) pR[j]=min(c,pR[j]); nL[c] = max(nL[c],a); nR[c] = min(nR[c],b); } for(int i=1;i<=n;i++) { if(nL[i]>nR[i]) f=1; if(pL[i]>pR[i]) f=1; } if(f==1) { printf("-1 "); continue; } init(); s=0, t=2*n+1; for(int i=1;i<=n;i++) Addedge(s,i,1), Addedge(i+n,t,1); for(int i=1;i<=n;i++) for(int j=pL[i];j<=pR[i];j++) if(nL[j]<=i&&i<=nR[j]) Addedge(i,j+n,1), u[i][j]=1; int pi = dinic(s,t); if(pi!=n) { printf("-1 "); continue; } memset(cun,0,sizeof cun); for(int pos=1;pos<=n;pos++) { for(int num=1;num<=n;num++) { if(cun[num]) continue; if(u[pos][num]==0) continue; init(); s=0, t=2*n+1; for(int i=1;i<=n;i++) { if(i>pos) Addedge(s,i,1); if(cun[i]==0&&i!=num) Addedge(i+n,t,1); } for(int i=pos+1;i<=n;i++) for(int j=pL[i];j<=pR[i];j++) if(nL[j]<=i&&i<=nR[j]) if(cun[j]==0&&j!=num) Addedge(i,j+n,1); pi = dinic(s,t); if(pi==n-pos) { ans[pos]=num; cun[num]=1; break; } } } for(int i=1;i<=n;i++) { printf("%d",ans[i]); if(i<n) printf(" "); else printf(" "); } } return 0; }