diff --git a/src/test.cpp b/src/test.cpp index db5cfe4..7af0f17 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1,211 +1,40 @@ -#include #include -#include -#include - -const int INF = 1e9; - -// 边的结构体 -struct Edge { - int to; // 边的终点 - int capacity; // 边的容量 - int rev; // 反向边的索引 -}; - -class MaxFlow { -private: - int n; // 顶点数 - std::vector> adj; // 邻接表 - std::vector level; // BFS分层图中的层次 - std::vector iter; // 当前弧优化 - - // 通过BFS构建分层图 - bool bfs(int s, int t) { - level.assign(n + 1, -1); - std::queue q; - level[s] = 0; - q.push(s); - while (!q.empty()) { - int u = q.front(); - q.pop(); - for (const auto& edge : adj[u]) { - if (edge.capacity > 0 && level[edge.to] < 0) { - level[edge.to] = level[u] + 1; - q.push(edge.to); - } - } - } - return level[t] != -1; - } - - // 通过DFS在分层图上寻找增广路并更新流量 - int dfs(int u, int t, int f) { - if (u == t) return f; - for (int& i = iter[u]; i < adj[u].size(); ++i) { - Edge& e = adj[u][i]; - if (e.capacity > 0 && level[u] < level[e.to]) { - int d = dfs(e.to, t, std::min(f, e.capacity)); - if (d > 0) { - e.capacity -= d; - adj[e.to][e.rev].capacity += d; - return d; - } - } - } - return 0; - } - - // 用于在残余网络中进行搜索,以确定S可达和T可达的节点 - void find_reachable(int start_node, std::vector& visited, bool reverse_edges = false) { - visited.assign(n + 1, false); - std::queue q; - q.push(start_node); - visited[start_node] = true; - - while (!q.empty()) { - int u = q.front(); - q.pop(); - - for(const auto& edge : adj[u]){ - // 在正向残余图上搜索(S可达性) - // S可达的条件是:从u到v还有剩余容量 - if (!reverse_edges && edge.capacity > 0 && !visited[edge.to]) { - visited[edge.to] = true; - q.push(edge.to); - } - // 在反向残余图上搜索(T可达性) - // v能到T的反向图 等价于 T能到v的反向图 - // 条件是:从u到v存在反向边容量 > 0 (即正向边流过流量) - if (reverse_edges && adj[edge.to][edge.rev].capacity > 0 && !visited[edge.to]) { - visited[edge.to] = true; - q.push(edge.to); - } - } - } - } - +using namespace std; +class Solution { public: - MaxFlow(int num_vertices) : n(num_vertices), adj(n + 1), level(n + 1), iter(n + 1) {} - - // 添加一条从u到v,容量为cap的边 - void add_edge(int u, int v, int cap) { - adj[u].push_back({v, cap, (int)adj[v].size()}); - adj[v].push_back({u, 0, (int)adj[u].size() - 1}); // 添加反向边 - } - - // 计算从s到t的最大流 - int dinic(int s, int t) { - int flow = 0; - while (bfs(s, t)) { - iter.assign(n + 1, 0); - int f; - while ((f = dfs(s, t, INF)) > 0) { - flow += f; + vector findDiagonalOrder(vector>& m) { + int x=0,y=0; + bool isup=true; + vector res; + res.reserve(m.size()); + #define isout (x<0||x>m.size()||y<0||y>m[0].size()) + do{ + res.push_back(m[x][y]); + if(isup){ + if(x==0){ + ++y; + isup=false; + }else{ + --x; + ++y; + } + }else{ + if(y==0){ + ++x; + isup=true; + }else{ + ++x; + --y; + } } - } - return flow; - } - - // 统计最小割的数量 - void count_min_cuts(int s, int t) { - // 第一步:运行Dinic算法计算最大流,这会改变adj列表中的capacity,形成残余网络 - int max_flow = dinic(s, t); - std::cout << "The minimum number of edges to remove is: " << max_flow << std::endl; - - // 保存原始图结构,因为add_edge会添加反向边 - std::vector> original_edges; - // 注意:这里需要根据实际建图的方式来获取原始边 - // 在这个简单实现中,我们硬编码原始边 - original_edges = { - {1, 2}, {1, 3}, {1, 4}, - {2, 4}, {2, 5}, - {3, 4}, - {4, 6}, - {5, 7}, - {6, 5}, {6, 7} - }; - - // 第二步:在残余网络中确定S可达和T可达的顶点 - std::vector reachable_from_s; - find_reachable(s, reachable_from_s, false); - - std::vector can_reach_t; // 这里的名字意思是“能到达T的节点” - find_reachable(t, can_reach_t, true); // 在反向图上从T开始搜索 - - std::cout << "The sets of edges forming a minimum cut are:" << std::endl; - - // 对于这个问题,我们可以直接找出所有"关键边",然后组合它们 - // 但对于更复杂的问题,需要更复杂的算法 - // 本题可以简化为:找到构成最小割的两个集合 - - // 割法 1:S-side = {S可达节点}, T-side = {S不可达节点} - std::cout << "Cut set 1 (based on S-reachability):" << std::endl; - int count1 = 0; - for (const auto& p : original_edges) { - int u = p.first; - int v = p.second; - if (reachable_from_s[u] && !reachable_from_s[v]) { - std::cout << " (" << u << ", " << v << ")" << std::endl; - count1++; - } - } - - // 割法 2:T-side = {T能到达的节点}, S-side = {T不能到达的节点} - std::cout << "Cut set 2 (based on T-reachability):" << std::endl; - int count2 = 0; - for (const auto& p : original_edges) { - int u = p.first; - int v = p.second; - // u在S侧(不能到达T),v在T侧(能到达T) - if (!can_reach_t[u] && can_reach_t[v]) { - std::cout << " (" << u << ", " << v << ")" << std::endl; - count2++; - } - } - - // 注意:如果两个割集完全一样,说明只有一个最小割。 - // 在本题中,这两个方法会找到两个不同的割集。 - if (count1 == max_flow && count2 == max_flow) { - if (count1 == count2) { // 检查两个割集是否相同, 简化处理 - // A more robust check would compare the sets of edges. - // For this specific problem, we know they are different. - std::cout << "Total distinct minimum cuts found: 2" << std::endl; - } else { - std::cout << "Total distinct minimum cuts found: 2 (sets are different sizes, but both min-cuts)" << std::endl; - } - } else { - std::cout << "Only one minimum cut found." << std::endl; - } - + }while(!(x==m.size()&&y==m[0].size())); + return res; } }; -int main() { - // 设置OI/ACM风格的快速IO - std::ios_base::sync_with_stdio(false); - std::cin.tie(NULL); +int main(){ - int num_vertices = 7; - int source = 1; - int sink = 7; - - MaxFlow solver(num_vertices); - - // 根据题目中的图构建网络 - // 所有边的容量都为1 - solver.add_edge(1, 2, 1); - solver.add_edge(1, 3, 1); - solver.add_edge(1, 4, 1); - solver.add_edge(2, 4, 1); - solver.add_edge(2, 5, 1); - solver.add_edge(3, 4, 1); - solver.add_edge(4, 6, 1); - solver.add_edge(5, 7, 1); - solver.add_edge(6, 5, 1); - solver.add_edge(6, 7, 1); - - solver.count_min_cuts(source, sink); - - return 0; -} + Solution s; + s.findDiagonalOrder({{1,2,3},{4,5,6},{7,8,9}}); +} \ No newline at end of file