• JZOJ 3163. 【GDOI2013模拟2】排列(二分图匹配)


    JZOJ 3163. 【GDOI2013模拟2】排列

    题目

    Description

    给你 M M M个对 1 1 1 N N N的排列的特征,特征有两种:

    1 1 1 x x x y y y v v v:排列的第 x x x个数到第 y y y个数之间的最大值为 v v v

    2 2 2 x x x y y y v v v:排列的第 x x x个数到第 y y y个数之间的最小值为 v v v.

    要求你还原出这个排列。

    Input

    第一行输入两个整数 N ( 1 ≤ N ≤ 200 ) N(1≤N≤200) N(1N200) M ( 0 ≤ M ≤ 40 , 000 ) M(0≤M≤40,000) M(0M40,000) N N N表示排列的数字个数, M M M表示特征数量。

    接下来 M M M行,每行描述一个特征。

    Output

    输出一行,满足所有特征的 1 1 1 N N N的一个排列。方案可能有很多,输出其中一个即可。如果无解,输出 − 1 -1 1

    Sample Input

    输入1:
    3 2
    1 1 1 1
    2 2 2 2

    输入2:
    4 2
    1 1 1 1
    2 3 4 1

    输入3:
    5 2
    1 2 3 3
    2 4 5 4

    Sample Output

    输出1:
    1 2 3

    输出2:
    -1

    输出3:
    1 2 3 4 5

    Data Constraint

    100%的数据满足 N ( 1 ≤ N ≤ 200 ) , M ( 0 ≤ M ≤ 40 , 000 ) N(1≤N≤200),M(0≤M≤40,000) N(1N200)M(0M40,000).

    题解

    • 由题目可知,最终的序列是 1 1 1 N N N的排列,数字没有重复,不难想到二分图匹配!
    • 怎么连边?
    • 根据题目的要求,可以得到每个位置的数字的上下界,全部连上一条边(最初的上下界为 [ 1 , N ] [1,N] [1,N])。
    • 但是,即使每个位置上的数都符合上下界的要求,但也不一定满足 M M M个区间的最大/最小值的要求。
    • 为什么?
    • 某区间中的数,假若它们上下界均为 [ l , r ] [l,r] [l,r],且要求该区间最小值为 l l l
    • 但如果直接跑一遍匈牙利算法,得到的这个区间所选的数不一定包含 l l l(因为还有其它选择),
    • 以至于这个区间的最小值不是要求的 l l l
    • 所以,光判断上下界是不行的!!!
    • 怎么修改?
    • 很简单,若某区间的最大/最小值为 x x x,则必须保证这个区间中的某个数向 x x x连了一条边,否则不符合题意,
    • 为了保证这样,就把该区间外的位置向 x x x连的边全部删除。
    • 如此以来,如果最终能跑出来,那么一定是符合每个区间的要求的。

    代码

    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct
    {
    	int a,l,r,s;
    }a[40010];
    int bz[210],c[210],d[210];
    int e[210][210],n;
    int dfs(int k)
    {
    	for(int i=1;i<=n;i++) if(e[k][i]&&!bz[i])
    	{
    		bz[i]=1;
    		if(d[i]==0||dfs(d[i]))
    		{
    			d[i]=k;
    			c[k]=i;
    			return 1;
    		}
    	}
    	return 0;
    }
    int main()
    {
    	int m,i,j;
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=m;i++) scanf("%d%d%d%d",&a[i].a,&a[i].l,&a[i].r,&a[i].s);	
    	for(i=1;i<=n;i++)
    	{
    		int l=1,r=n;
    		for(j=1;j<=m;j++) 
    		{
    			if(a[j].a==1&&i>=a[j].l&&i<=a[j].r&&a[j].s<r) r=a[j].s;
    			if(a[j].a==2&&i>=a[j].l&&i<=a[j].r&&a[j].s>l) l=a[j].s;
    		}
    		for(j=l;j<=r;j++) e[i][j]=1;
    	}
    	for(i=1;i<=m;i++)
    	{
    		for(j=1;j<=n;j++) if(j<a[i].l||j>a[i].r) e[j][a[i].s]=0;
    	}
    	int s=0;
    	for(i=1;i<=n;i++) 
    	{
    		memset(bz,0,sizeof(bz));
    		if(dfs(i)) s++;
    	}
    	if(s<n) 
    	{
    		printf("-1");
    		return 0;
    	}
    	for(i=1;i<=n;i++) printf("%d ",c[i]);
    	return 0;
    }
    
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    在linux下使用sqlcmd
    sqlserver 索引的结构及其存储,索引内容
    据库被标记为RESTORING的处理方式,正在还原中,正在恢复
    sql语句的优化分析
    SQL Server表分区-水平分区
    JavaScript Structure
    JS----Issue
    JavaScript Book Plan
    LINQ
    About JavaScript
  • 原文地址:https://www.cnblogs.com/LZA119/p/13910086.html
Copyright © 2020-2023  润新知