hdu6321 对一个图进行加边或删边操作(n<=10),在每次操作后求图的匹配数为k的方案数,其中k=1,2,...n/2。
由于点的数目很少,考虑状压dp,dp[k][i]表示第k次操作后在i状态下点集中最大匹配的方案数,显然对于x个点的状态匹配数最多是x/2个。
考虑加边u-v的操作,如果对于一个状态pre,状态中没有u和v两个点,那么就可以从pre状态转移到now状态,其中now是pre以及u和v的并。删除边的时候同理。可以看到这里转移的时候只需要前一次操作的结果,于是可以使用滚动数组减小空间的使用。
#include
#include
#include
#include
#include
#include
#include
hdu6331 给出一个n个点和m条边的图,要求q次查询,每次查询从s到t经过不少于k条边(可重复)的最短距离。n<=50,m,k<=10000,q<=100000。
显然要先预处理点之间的距离,直接处理的复杂度是O(n^3*m),是无法接受的,考虑一个分块的dp。
dp[i][j][k]表示从i到j恰好经过k条边的最短距离
dp1[i][j][k]表示从i到j至少经过k条边的最短距离
dp2[i][j][k]表示从i到j恰好经过k*100条边的最短距离 ,k<=100
dp[i][j][k]用原图就可以处理出来,而dp1[i][j][k]=min(dp[i][t][k]+dis[t][j]),其中dis[][]是原图处理出的传递闭包。
以及dp2[i][j][k]=min(dp2[i][t][k-1]+dp[k][j][100])。
最后查询时枚举中间点e,ans=min(dp2[i][e][k/100]+dp1[e][t][k%100])。
#include
#include
#include
#include
#define maxn 51
#define maxm 102
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int kase,s,e,t,n,m,q,a,b,x;
int dis[maxn][maxn];
int maze[maxn][maxn];
int dp[maxn][maxn][maxm];
int dp1[maxn][maxn][maxm];
int dp2[maxn][maxn][maxm];
//0 k个 1 至少k 2 k*100个
int Min(int a,int b)
{
if(a < 0)return b;
else if(b < 0)return a;
return a