题目链接:魔术球问题
蒟蒻认为本题的关键还是在一个边与点的关系
本题一看就是图论…当然不少人(包括蒟蒻 是学习网络流来的…
显然我们要对球或杆进行操作
由于关系的建立条件是球的相邻放置条件
所以以球为元素建图 而一个杆子就是一条从起点到终点的路径
那么 最多能放的杆子数就是最小路径覆盖数
但是网络流维护的是边的关系
所以我们使用点拆边技能
把入度边和出度边分两个点存 然后在这两个点中间连一条路
注:公式:最小路径覆盖数=点数-最大匹配数
问题是题目给的是柱子数啊!
然鹅 对于能放的球数增加 柱子的数量单调增
因为球从下向上放 能放的球多了柱子数不可能减啊
debug中的错误:
1. S,T定太小 冲突 数组定太小
2. 反向边初始容量为0
3. 把next定成bool型。。。
1 int main(){ 2 scanf("%d", &n); 3 int cnt = 0, now = 0; 4 memset(head, -1, sizeof(head)); 5 memset(next, -1, sizeof(next)); 6 S = N - 3, T = N - 2; 7 while(cnt <= n){ 8 now++; 9 addedge(S, now << 1, 1); addedge(now << 1 | 1, T, 1); 10 for(int i = sqrt(now) + 1; i * i < (now << 1); i++) 11 addedge((i * i - now) << 1, now << 1 | 1, 1); 12 if(!dinic()) ub[++cnt] = now; 13 } 14 printf("%d\n", --now); 15 for(int i = 1; i <= now; i++){ 16 if(!vis[i]){ 17 int k = i; 18 while(k < (S >> 1) && k != -1 && !vis[k]){ 19 printf("%d ", k); 20 vis[k] = 1; 21 k = next[k]; 22 } 23 printf("\n"); 24 } 25 } 26 return 0; 27 }