bzoj 4715 囚人的旋律 (dp)

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/zzk_233/article/details/82972527

这是一个逆序对图。。我们可以设一个数组a表示每一个位置的权值。它只有在存在逆序对时才连边,而即是独立集又是覆盖集

的情况就是这些点之间没有连边,并且其他的数字都是他们的逆序对。。所以可以考虑成数列的形式。设f表示到当前点为止的

方案数(选择当前点),维护tmp为a[tmp]>a[i]&&a[i]<a[j]。。。所以就是a[tmp]>a[j]的最小值,

因为只保证a[tmp]<a[i]并不能限制j的选择,所以只要保证这个,

中间所有的数字都可以和i或者i之前的点(因为i是最大的,用i判定)构成逆序对。并且只要比最小值tmp小的j就可以转移

并且之前的f都确定了选择的点是递增的,不会有不合法情况。所以是对的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define mode 1000000007
using namespace std;
typedef long long ll;
ll f[1005];
int val[1005][1005],n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,a,b;i<=m;i++)
    {
    	scanf("%d%d",&a,&b);val[a][b]=val[b][a]=1;
    }
    f[0]=1;
    for(int i=0;i<=n;i++)
    {
    	int tmp=0;
    	for(int j=i+1;j<=n+1;j++)
    	{
	    	if((!tmp||val[tmp][j])&&!val[i][j])
	    	{
	    		f[j]=(f[j]+f[i])%mode;
	    		tmp=j;
	    	}
	    }
    }
    printf("%I64d",f[n+1]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zzk_233/article/details/82972527
今日推荐