http://www.bnuoj.com/v3/contest_show.php?cid=6865#problem/H
5 1 1 1 5 1 1 5 5 3 1 1 1 2 2 1 2 2
1 2 3 4 5 -1
/** 2015年四川省赛||弱校联萌十一大决战之强力热身 H. Range Query 二分图的最大匹配确定匹配顺序 题目大意:给定一个序列1~n,然后1~n个位置,现在给定一些子区间的最大最小值,问是否可以一个位置对应一个数,输出字典序最小的 解题思路:看叉姐的思路http://talk.icpc-camp.org/d/117-2015-h-range-query */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; const int maxn=155; int n,m1,m2,low[maxn],up[maxn],start[maxn],tail[maxn]; int a[maxn][maxn]; int used[maxn],link[maxn],vis[maxn]; bool dfs(int u) { for(int v=1;v<=n;v++) { if(a[u][v]&&!vis[v]&&!used[v]) { vis[v]=1; if(link[v]==-1||dfs(link[v])) { link[v]=u; return true; } } } return false; } bool solve(int s) { memset(link,-1,sizeof(link)); for(int u=s;u<=n;u++) { memset(vis,0,sizeof(vis)); if(!dfs(u))return false; } return true; } int main() { while(~scanf("%d%d%d",&n,&m1,&m2)) { for(int i=1; i<=n; i++) { low[i]=start[i]=1; up[i]=tail[i]=n; } for(int i=0; i<m1; i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); for(int j=a; j<=b; j++) low[j]=max(low[j],c); start[c]=max(start[c],a); tail[c]=min(tail[c],b); } for(int i=0;i<m2;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); for(int j=a;j<=b;j++)up[j]=min(up[j],c); start[c]=max(start[c],a); tail[c]=min(tail[c],b); } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { a[i][j]=low[i]<=j&&j<=up[i]&&start[j]<=i&&i<=tail[j]; } } memset(used,0,sizeof(used)); if(solve(1)) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(a[i][j]&&!used[j]) { used[j]=1; if(solve(i+1)) { printf("%d%c",j," \n"[i==n]); break; } used[j]=0; } } } } else puts("-1"); } return 0; }