A – (Lindström–Gessel–Viennot lemma)
这个定理是解决网格图不相交路径计数的
本题就相当于在一个n*m的网格中求两条不相交的线。
题解:01 和 12 的分界线 是 (n, 0) 到 (0, m) 的两条不相交(可重合)路径 平移其中一条变成 (n-1, -1) 到 (-1, m-1) 变成起点 (n, 0) 和 (n-1, -1),终点 (0, m) 和 (-1, m-1) 的严格不相交路径
套 Lindström–Gessel–Viennot lemma
答案是 C(n+m, n )*C (n+m,n) - C(n+m, m - 1)*C(n+m, n-1)
#include<bits/stdc++.h>
using namespace std;
#define maxn 2005
#define mod 1000000007
#define ll long long
ll a[maxn][maxn];
int main()
{
a[0][0]=a[1][0]=a[1][1]=1;
for(int i=2;i<=2000;i++){
a[i][0]=1;
for(int j=1;j<=i;j++)
a[i][j]=(a[i-1][j]+a[i-1][j-1])%mod;
}
int n,m;
while(scanf("%d %d",&n,&m)!=EOF){
ll s1=a[n+m][n]*a[n+m][m]%mod;
ll s2=a[n+m][m-1]*a[n+m][n-1]%mod;
ll ans=(s1-s2+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
D – (暴力匹配)
直接n ! 枚举可能的同构方案
Hash 去重即可 ,也可除以自同构的方案数
#include<bits/stdc++.h>
using namespace std;
const int maxn=10;
struct node{
int t,next;
}chu[100];
int head[maxn];
int sz;
void add(int f,int t)
{
chu[sz].t=t;
chu[sz].next=head[f];
head[f]=sz++;
}
int mp2[10][10],mp1[10][10];
int qu[100],biao[100],ans,ans2,n;
void init()
{
memset(mp2,0,sizeof(mp2));
memset(mp1,0,sizeof(mp1));
memset(biao,0,sizeof(biao));
ans=0,ans2=0;
memset(head,-1,sizeof(head));
sz=0;
}
bool suan1()
{
bool fa=true;
for(int i=1;i<=n&&fa;i++){
for(int j=head[i];~j;j=chu[j].next)
{
int to=chu[j].t;
// cout<<i<<" "<<to<<endl;
if(mp2[qu[i]][qu[to]]==0) {fa=false;break;}
}
}
//cout<<endl;
if(fa) return true;
else return false;
}
bool suan2()
{
bool fa=true;
for(int i=1;i<=n&&fa;i++){
for(int j=head[i];~j;j=chu[j].next)
{
int to=chu[j].t;
if(mp1[qu[i]][qu[to]]==0) {fa=false;break;}
}
}
if(fa) return true;
else return false;
}
void dfs(int cn)
{
if(cn>n){
if(suan1()) ans++;
if(suan2()) ans2++;
return;
}
for(int i=1;i<=n;i++){
if(biao[i]==0){
biao[i]=1;
qu[cn]=i;
dfs(cn+1);
biao[i]=0;
}
}
return;
}
int main()
{
int num1,num2;
while(scanf("%d %d %d",&n,&num1,&num2)!=EOF)
{
init();
for(int i=0;i<num1;i++) {
int u,v;
scanf("%d %d",&u,&v);
add(u,v);add(v,u);
mp1[u][v]=mp1[v][u]=1;
}
for(int i=0;i<num2;i++) {
int u,v;
scanf("%d %d",&u,&v);
mp2[u][v]=mp2[v][u]=1;
}
dfs(1);
// cout<<ans<<" "<<ans2<<endl;
printf("%d\n",ans/ans2);
}
return 0;
}