NC21655. 牛牛的汉密尔顿路径
描述
输入描述
第一行输入两个整数n,m (2≤ n ≤ 100, 1 ≤ m ≤ 2500)表示点数与边数
第二行输入n个整数表示每个点颜色color[i], (0 ≤ color[i] ≤ 9),每种颜色最多出现10次
第三行输入m个数表示每条边的起点
第四行输入m个数表示每条边的终点
输出描述
输出一个整数
示例1
输入:
9 12 0 0 0 1 1 1 2 2 2 0 1 2 3 4 5 6 7 8 0 3 6 1 2 0 4 5 3 7 8 6 3 6 0
输出:
0
示例2
输入:
9 12 0 0 0 1 1 1 2 2 2 0 1 2 3 4 5 6 7 8 0 4 8 1 2 0 4 5 3 7 8 6 3 7 2
输出:
24
C++(clang++ 11.0.1) 解法, 执行用时: 96ms, 内存消耗: 9980K, 提交时间: 2022-09-19 20:02:48
#pragma G++ optimize("Ofast") #pragma G++ optimize("unroll-loops") #include<iostream> #include<algorithm> #include<vector> #include<cstring> #include<functional> #include<queue> #include<unordered_map> #include<map> #include<set> #include<stack> #include<cmath> #include<bitset> #include<iomanip> #include<numeric> using namespace std; using lli = long long; using pii = pair<lli, lli>; const int INF = 1e9; const lli inf = 1e18; const int maxn = 1e5+5; const lli mod = 1e9+7; int n, m, ans, ed; int a[105], b[105], edge[2505][2], dis[105][105]; int dp1[15][1<<12][15][15], dp2[1<<12][105]; vector<int> c[10]; inline bool f(int x, int y) { return x>>y&1; } inline void add(int &x, int y) { x+=y; if(x>=mod) x-=mod; } void work1(int col) { int len = c[col].size(), cs = (1<<len)-1; for(int i=0; i<len; ++i) { dp1[col][1<<i][i][i] = 1; } for(int st=1; st<cs; st++) { for(int i=0; i<len; ++i) { if(!f(st, i)) continue; for(int j=0; j<len; ++j) { if(!f(st, j)) continue; for(int k=0; k<len; ++k) { if(f(st, k) || !dis[c[col][j]][c[col][k]]) continue; add(dp1[col][st|(1<<k)][i][k], dp1[col][st][i][j]); } } } } for(int i=0; i<len; ++i) { for(int j=0; j<len; ++j) { add(dp2[1<<col][c[col][i]], dp1[col][cs][j][i]); } // cout<<col<<' '<<c[col][i]<<' '<<dp2[1<<col][c[col][i]]<<'\n'; } } void work2(int st, int x, int y) { int col = a[y], len = c[col].size(), cs = (1<<len)-1; for(int i=0; i<len; ++i) { add(dp2[st|(1<<col)][c[col][i]], 1ll*dp2[st][x]*dp1[col][cs][b[y]][i]%mod); } } void solve() { cin>>n>>m; for(int i=0; i<n; ++i) { cin>>a[i]; b[i] = c[a[i]].size(); c[a[i]].push_back(i); ed|=1<<a[i]; } for(int i=1; i<=m; ++i) { cin>>edge[i][0]; } for(int i=1; i<=m; ++i) { cin>>edge[i][1]; dis[edge[i][0]][edge[i][1]] = dis[edge[i][1]][edge[i][0]] = 1; } for(int col=0; col<10; ++col) { work1(col); } for(int st=1; st<ed; ++st) { for(int i=1; i<=m; ++i) { bool f1 = f(st, a[edge[i][0]]), f2 = f(st, a[edge[i][1]]); if(f1 && !f2) work2(st, edge[i][0], edge[i][1]); if(!f1 && f2) work2(st, edge[i][1], edge[i][0]); } } for(int i=0; i<n; ++i) { add(ans, dp2[ed][i]); } cout<<ans<<'\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t=1; // cin>>t; while(t--)solve(); return 0; }