很容易会想到是最大流建边,但是同样的这里有坑点,就是有的人去输出边的时候,去把残余网络的流为0的边给输出了,其实不然,我们应当输出的是那些最后跑到深度为0的不能再走下去的点,只要把他们割了,就一定会是最优的解。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define HalF (l + r)>>1 #define lsn rt<<1 #define rsn rt<<1|1 #define Lson lsn, l, mid #define Rson rsn, mid+1, r #define QL Lson, ql, qr #define QR Rson, ql, qr #define myself rt, l, r using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 107, maxE = 2e3 + 7, S = 1, T = 2; int N, M, cnt, head[maxN], cur[maxN]; struct Eddge { int nex, to, flow, old; Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), flow(c), old(c) {} }edge[maxE]; inline void addEddge(int u, int v, int flow) { edge[cnt] = Eddge(head[u], v, flow); head[u] = cnt++; } inline void _add(int u, int v, int flow) { addEddge(u, v, flow); addEddge(v, u, 0); } int deep[maxN]; queue<int> Q; inline bool bfs() { memset(deep, 0, sizeof(deep)); deep[S] = 1; while(!Q.empty()) Q.pop(); Q.push(S); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i=head[u], v, f; ~i; i=edge[i].nex) { v = edge[i].to; f = edge[i].flow; if(f && !deep[v]) { deep[v] = deep[u] + 1; Q.push(v); } } } return deep[T]; } inline int dfs(int u, int dist) { if(u == T) return dist; for(int &i=cur[u], v, f; ~i; i=edge[i].nex) { v = edge[i].to; f = edge[i].flow; if(f && deep[v] == deep[u] + 1) { int di = dfs(v, min(dist, f)); if(di) { edge[i].flow -= di; edge[i^1].flow += di; return di; } } } return 0; } inline void Dinic() { while(bfs()) { for(int i=1; i<=N; i++) cur[i] = head[i]; while(dfs(S, INF)) ; } } bool used[55][55]; inline void Out(int u, int fa) { for(int i=head[u], v, f; ~i; i=edge[i].nex) { v = edge[i].to; f = edge[i].flow; if(v == fa) continue; if(!deep[v] && edge[i].old) { if(used[u][v]) continue; used[u][v] = used[v][u] = true; printf("%d %d\n", u, v); } else if(edge[i].old > f) { Out(v, u); } } } inline void init() { cnt = 0; memset(head, -1, sizeof(head)); memset(used, false, sizeof(used)); } int main() { int Cas = 0; while(scanf("%d%d", &N, &M) && (N || M)) { if(Cas++) printf("\n"); init(); for(int i=1, u, v, w; i<=M; i++) { scanf("%d%d%d", &u, &v, &w); _add(u, v, w); _add(v, u, w); } Dinic(); Out(S, -1); } return 0; }