1. 程式人生 > >【bzoj4715】囚人的旋律 dp

【bzoj4715】囚人的旋律 dp

sin 輸入 can for bzoj ros print algorithm 人的

題目描述

給你一個 $1\sim n$ 的排列 $a_i$ ,若 $i\le j$ 且 $a_i\ge a_j$ ,則 $i$ 到 $j$ 有一條邊。現在給你這張圖,求既是獨立集(任意兩個選定點都沒有邊)又是覆蓋集(任意一個非選定點都存在一個選定點與之相連)的點集數模 $10^9+7$ 。

輸入

輸入第一行含有兩個整數n和m,表示逆序圖的點數和邊數。 接下來m行,每行描述一條邊。每行包含兩個1~n的整數,代表邊的兩個端點。保證沒有重邊和自環。 保證給定的圖是一個合法的逆序圖,即,存在至少一個序列,按照題目描述中所述方法得到的逆序圖是給定的圖。 n≤1000,0≤m≤(n(n-1))/2

輸出

輸出一個整數,表示方案數對1,000,000,007取模得到的結果。

樣例輸入

5 5
2 4
2 5
1 4
3 4
3 5

樣例輸出

3


題解

dp

我們去 %CQzhangyu 吧

#include <cstdio>
#include <algorithm>
#define mod 1000000007
using namespace std;
int v[1010][1010] , f[1010];
int main()
{
	int n , m , i , j , k , x , y , ans = 0;
	bool flag;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &x , &y) , v[min(x , y)][max(x , y)] = 1;
	for(i = 1 ; i <= n ; i ++ ) v[0][i] = 1;
	for(i = 1 ; i <= n ; i ++ )
	{
		if(!f[i]) f[i] = 1;
		flag = 0;
		for(k = 0 , j = i + 1 ; j <= n ; j ++ )
		{
			if(!v[i][j])
			{
				flag = 1;
				if(v[k][j]) k = j , f[j] = (f[j] + f[i]) % mod;
			}
		}
		if(!flag) ans = (ans + f[i]) % mod;
	}
	printf("%d\n" , ans);
	return 0;
}

【bzoj4715】囚人的旋律 dp