【2011集训队出题】连边___dp+思维

题目大意:

有N个点(编号1到N)组成的无向图,已经为你连了M条边。请你再连K条边,使得所有的点的度数都是偶数。求有多少种连的方法。要求你连的K条边中不能有重边,但和已经连好的边可以重。不允许自环的存在。求连边的方法数。我们只关心它模10007的余数。

30%的数据满足:
N≤200
100%的数据满足:
N≤1000,M≤N,K≤1000,K≤N(N-1)/2

题解:

这题可以用除以K!的方法把问题转化为边之间计次序。
设f(i,j)表示用i条边,使得j个点的度数为奇数的情况下连边的方法数:
分类讨论第i条边连接的点的度数的奇偶性。
如果它连着两个奇数点,那么原来那两个点的度数是偶数,总奇数点个数比现在少2;
如果这条边连接的点是一奇一偶,那么奇数点的个数不变。
如果连接着两个偶数点,那么原来这两个点都是奇数点,总奇数点的个数比现在多2。
通过枚举这条边连接的两个点的奇偶情况,f(i,j)可以分别转移到
f(i-1,j)*(N-j)*j,f(i-1,j-2)*C(n-(j-2),2),f(i-1,j+2)*C(j+2,2)
注意到这样转移的话无法保证没有重边。于是,让我们考虑第i条边和之前的第a条边重复的情况。a有i-1种取值。除去第i条和第a条边,所有的点的度数的奇偶性不变,于是问题转化为f(i-2,j)。这样,我们知道了第i条边和之前的某些边重复的方法数是f(i-2,j)*(i-1)*C(n,2)
于是,总的转移方程是
f(i,j)=f(i-1,j)* (N-j)* j+f(i-1,j-2) * C (j,2)+ f (i-1,j+2) * C(N-j,2)-f(i-2,j) * (C(N,2)-(i-2))
答案就是f(K,A)/K!
转移的时候要注意取模以及边界情况的讨论。
初值:f[0][一开始的奇数点数]=1

代码:

const
      modn=10007;
var
      f:Array [0..1001,0..1001] of int64;
      a,c:Array [0..1001] of int64;
      op,i,j,n,m,k,x,y:longint;

function need(x:int64):int64;
begin
      if x<2 then exit(0);
      exit(x*(x-1) div 2);
end;

begin
      readln(n,m,k);
      a[0]:=1;
      a[1]:=1;
      for i:=2 to 1000 do a[i]:=(modn-modn div i)*a[modn mod i] mod modn;
      for i:=1 to m do
         begin
               readln(x,y);
               inc(c[x]);
               inc(c[y]);
         end;
      op:=0;
      for i:=1 to n do
        if odd(c[i]) then inc(op);
      f[0,op]:=1;
      for i:=1 to k do
        for j:=0 to n do
          begin
               if j>=2 then f[i,j]:=(f[i,j]+f[i-1,j-2]*need(n-(j-2))) mod modn;
               if j<=n-2 then f[i,j]:=(f[i,j]+f[i-1,j+2]*need(j+2)) mod modn;
               if i>=2 then f[i,j]:=(f[i,j]-f[i-2,j]*(need(n)-i+2)) mod modn;
               f[i,j]:=(f[i,j]+f[i-1,j]*(n-j)*j) mod modn;
               f[i,j]:=(f[i,j]+modn) mod modn;
               f[i,j]:=f[i,j]*a[i] mod modn;
          end;
      writeln(f[k,0]);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值