题意:n根柱子 把编号1,2,3....的球依次插到柱子上去
需要满足相邻的两个球编号加起来为完全平方数 n < 55
题解:网络流24(23)题里的
但是一直不知道怎么建图 或者说建图的意义
一般都要套路拆点 我的理解就是实际问题背景每个点是需要双向边的 但是网络流算法要建反向边 所以就拆点防止重边 意义更明确
这个题的话把小球拆点就表示 一个放前面 一个放后面的情况 然后按题意建图 跑最大流
我最开始以为一条增广路代表一根柱子 其实不是 这里柱子的意义更抽象
模拟一下程序后发现 在依次加球的过程中 最大流跑通表示的是这个球可以直接接在当前安排方式的后面
如果跑不通 就要新开柱子了 同时跑新的最大流也能保证反悔操作
#include <bits/stdc++.h> using namespace std; int n, cnt, p, num, s, t, maxflow; struct node { int to, nex, val; }E[200005]; int head[4005]; int cur[4005]; void addedge(int x, int y, int va) { E[++cnt].to = y; E[cnt].nex = head[x]; E[cnt].val = va; head[x] = cnt; E[++cnt].to = x; E[cnt].nex = head[y]; E[cnt].val = 0; head[y] = cnt; } int dep[4005]; int to[4005]; int inque[4005]; bool bfs() { for(int i = 0; i <= num * 2 + 2; i++) cur[i] = head[i], dep[i] = 0x3f3f3f3f, inque[i] = 0; dep[s] = 0; queue<int> que; que.push(s); inque[s] = 1; while(!que.empty()) { int u = que.front(); que.pop(); for(int i = head[u]; i; i = E[i].nex) { int v = E[i].to; if(E[i].val > 0 && dep[v] > dep[u] + 1) { dep[v] = dep[u] + 1; if(!inque[v]) { inque[v] = 1; que.push(v); } } } } if(dep[t] != 0x3f3f3f3f) return true; return false; } int vis; int dfs(int x, int flow) { if(x == t) { vis = 1; maxflow += flow; return flow; } int rflow = 0; int used = 0; for(int i = cur[x]; i; i = E[i].nex) { cur[x] = i; int v = E[i].to; if(E[i].val > 0 && dep[v] == dep[x] + 1) { if(rflow = dfs(v, min(flow - used, E[i].val))) { to[x / 2] = v / 2; used += rflow; E[i].val -= rflow; E[i ^ 1].val += rflow; if(used == flow) break; } } } return used; } void dinic() { maxflow = 0; while(bfs()) { vis = 1; while(vis) { vis = 0; dfs(s, 100000000); } } } int ans[60]; int main() { p = num = 0; cnt = 1; scanf("%d", &n); s = 0; t = 1; while(p <= n) { num++; addedge(s, num << 1, 1); addedge(num << 1 | 1, t, 1); for(int i = sqrt(num) + 1; i * i < 2 * num; i++) { addedge((i * i - num) << 1, num << 1 | 1, 1); } dinic(); if(!maxflow) { ans[++p] = num; } } printf("%d ", num - 1); for(int i = 1; i <= n; i++) { printf("%d", ans[i]); for(int j = ans[i]; to[j]; j = to[j]) printf(" %d", to[j]); puts(""); } return 0; }