Aiiage Camp Day5 A Rikka with Linker

题意

  n个点,m个关系。a依赖b则a需要出现在b前。

  求满足所有关系的最短序列长度。

  n<18, m<n(n-1)

题解

  问题事实上等价于有向有环图的拓扑排序。

  所以用拓扑排序结合搜索有个显然的2^n*n^2的做法。

  赛场上写的有点丑T了。

  标算是DP。F[S]表示添加了集合S的最短长度。对于每个S,枚举添加点x:若x被依赖的所有点都出现过,则只需要在当前序列最后添加x;否则,需要在最后再添加一个x使尚未添加的点满足条件。

  复杂度O(2^n*n)。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int h[30], f[300000];
 5 
 6 int main()
 7 {
 8     int T;
 9     for (scanf("%d", &T); T; T--)
10     {
11         memset(h, 0, sizeof(h));
12         int n, m;
13         scanf("%d%d", &n, &m);
14         for (int i = 0; i < m; ++i)
15         {
16             int u, v;
17             scanf("%d%d", &u, &v);
18             h[v] ^= 1 << (u - 1);
19         }
20         int maxx(pow(2, n));
21         for (int i = 0; i < maxx; ++i)
22             f[i] = 2 * n;
23         f[0] = 0;
24         for (int i = 0; i < maxx; ++i)
25             for (int j = 1; j <= n; ++j)
26                 if (!(i & (1 << (j - 1))))
27                     if ((h[j] ^ i) & h[j])
28                         f[i ^ (1 << (j - 1))] = min(f[i ^ (1 << (j - 1))], f[i] + 2);
29                     else
30                         f[i ^ (1 << (j - 1))] = min(f[i ^ (1 << (j - 1))], f[i] + 1);
31         printf("%d
", f[maxx - 1]);
32     }
33     
34     return 0;
35 }
原文地址:https://www.cnblogs.com/aseer/p/8479842.html