01、飞行员配对方案问题
英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次 派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
二分图最大匹配
1 #include <bits/stdc++.h> 2 #define min(a, b) ((a) < (b) ? (a) : (b)) 3 using namespace std; 4 const int MAXN = 100000; 5 const int INF = 0x3f3f3f3f; 6 inline void read(int &x) 7 { 8 x = 0;char ch = getchar(), c = ch; 9 while(ch < ‘0‘ || ch > ‘9‘)c = ch, ch = getchar(); 10 while(ch <= ‘9‘ && ch >= ‘0‘)x = x * 10 + ch - ‘0‘, ch = getchar(); 11 if(c == ‘-‘)x = -x; 12 } 13 14 struct Edge 15 { 16 int u,v,w,nxt; 17 Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;} 18 Edge(){} 19 }edge[100010]; 20 int head[MAXN<<1],cnt = 1,q[MAXN<<1],h[MAXN<<1],ans=0,n,m,S,T,fa[MAXN <<1]; 21 inline void insert(int a,int b,int c) 22 { 23 edge[++cnt] = Edge(a,b,c,head[a]); 24 head[a] = cnt; 25 edge[++cnt] = Edge(b,a,0,head[b]); 26 head[b] = cnt; 27 } 28 bool bfs() 29 { 30 int he = 0, ta = 1; 31 memset(h, -1, sizeof(h)); 32 q[he] = S, h[S] = 0; 33 while(he < ta) 34 { 35 int now = q[he ++]; 36 for(int pos = head[now];pos;pos = edge[pos].nxt) 37 { 38 int v = edge[pos].v; 39 if(h[v] == -1 && edge[pos].w) 40 { 41 h[v] = h[now] + 1; 42 q[ta ++] = v; 43 } 44 } 45 } 46 return h[T] != -1; 47 } 48 49 int dfs(int x, int f) 50 { 51 if(x == T) return f; 52 int w, used = 0; 53 for(int pos = head[x];pos;pos = edge[pos].nxt) 54 { 55 int v = edge[pos].v; 56 if(h[v] == h[x] + 1) 57 { 58 w = dfs(v, min(f - used, edge[pos].w)); 59 if(w) fa[x] = v; 60 edge[pos].w -= w; 61 edge[pos ^ 1].w += w; 62 used += w; 63 if(used == f) return f; 64 } 65 } 66 if(!used) h[x] = -1; 67 return used; 68 } 69 70 void dinic() 71 { 72 while(bfs()) ans += dfs(S, INF); 73 } 74 75 int vis[MAXN << 1]; 76 77 int main() 78 { 79 read(m), read(n); 80 int tmp1, tmp2; 81 S = n + m + 2, T = n + m + 3; 82 while(scanf("%d %d", &tmp1, &tmp2) != EOF && tmp1 != -1) 83 insert(tmp1, tmp2, 1); 84 for(register int i = 1;i <= m;++ i) 85 insert(S, i, 1); 86 for(register int i = m + 1;i <= m + n;++ i) 87 insert(i, T, 1); 88 dinic(); 89 printf("%d\n", ans); 90 if(ans == 0) printf("No Solution!\n"); 91 else 92 for(int i = 1;i <= m;++ i) 93 if(fa[i]) 94 printf("%d %d\n", i, fa[i]); 95 return 0; 96 }
02、太空飞行计划问题
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E= {E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集RjÍI。配置仪器 Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而 配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
最大(小)权闭合子图。S连实验,T连仪器,实验与对应仪器连INF,割与S连的边意味着不做这个实验,割与T连的边意味着用这个仪器
于是S集合代表选择的实验和仪器,求最小割,总收益-最小割即为答案
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <cmath> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 template <class T> 13 inline void swap(T& a, T& b) 14 { 15 T tmp = a;a = b;b = tmp; 16 } 17 inline void read(int &x) 18 { 19 x = 0;char ch = getchar(), c = ch; 20 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 21 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 22 if(c == ‘-‘) x = -x; 23 } 24 25 const int INF = 100000; 26 const int MAXN = 3000 + 10; 27 const int MAXM = MAXN * MAXN; 28 29 struct Edge 30 { 31 int u,v,w,nxt; 32 Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;} 33 Edge(){} 34 }edge[MAXM << 1]; 35 int head[MAXN], cnt = 1; 36 inline void insert(int u, int v, int w) 37 { 38 edge[++cnt] = Edge(u,v,w,head[u]); 39 head[u] = cnt; 40 edge[++cnt] = Edge(v,u,0,head[v]); 41 head[v] = cnt; 42 } 43 44 int q[MAXN << 1], h[MAXN << 1], ans, S, T, he, ta; 45 46 bool bfs() 47 { 48 int he = 0, ta = 1; 49 memset(h, -1, sizeof(h)); 50 q[he] = S, h[S] = 0; 51 while(he < ta) 52 { 53 int now = q[he ++]; 54 for(int pos = head[now];pos;pos = edge[pos].nxt) 55 { 56 int v = edge[pos].v; 57 if(h[v] == -1 && edge[pos].w) 58 { 59 h[v] = h[now] + 1; 60 q[ta ++] = v; 61 } 62 } 63 } 64 return h[T] != -1; 65 } 66 67 int dfs(int x, int f) 68 { 69 if(x == T) return f; 70 int w, used = 0; 71 for(int pos = head[x];pos;pos = edge[pos].nxt) 72 { 73 int v = edge[pos].v; 74 if(h[v] == h[x] + 1) 75 { 76 w = dfs(v, min(f - used, edge[pos].w)); 77 edge[pos].w -= w; 78 edge[pos ^ 1].w += w; 79 used += w; 80 if(used == f) return f; 81 } 82 } 83 if(!used) h[x] = -1; 84 return used; 85 } 86 87 void dinic() 88 { 89 while(bfs()) ans += dfs(S, INF); 90 } 91 92 int n,m,sum,vis[MAXN]; 93 94 int main() 95 { 96 read(m), read(n);S = n + m + 100;T = n + m + 200; 97 for(int i = 1;i <= m;++ i) 98 { 99 char c = 0;int w, tmp = 0; 100 read(w);sum += w; 101 insert(S, i, w); 102 while(c != ‘\n‘ && c != ‘\r‘) 103 { 104 c = getchar(); 105 while(c >= ‘0‘ && c <= ‘9‘) 106 tmp = tmp * 10 + c - ‘0‘, c = getchar(); 107 if(tmp) insert(i, tmp + m, INF), tmp = 0; 108 } 109 } 110 for(int i = 1;i <= n;++ i) 111 { 112 int tmp;read(tmp); 113 insert(i + m, T, tmp); 114 } 115 dinic(); 116 for(int pos = head[S];pos;pos = edge[pos].nxt) 117 if(edge[pos].w) 118 vis[edge[pos].v] = 1; 119 for(int i = 1;i <= m;++ i) if(h[i] != -1) printf("%d ", i); 120 putchar(‘\n‘); 121 for(int i = m + 1;i <= n + m;++ i) if(h[i] != -1) printf("%d ", i - m);putchar(‘\n‘); 122 printf("%d", sum - ans); 123 return 0; 124 }
03、最小路径覆盖问题
«问题描述:
给定有向图G=(V,E)。设P 是G 的一个简单路(顶点不相交)的集合。如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖。P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0。G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖。设计一个有效算法求一个有向无环图G 的最小路径覆盖。提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下:
每条边的容量均为1。求网络G1的( 0 x , 0 y )最大流。
«编程任务:
对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。
每个点拆成x,x‘,S->x, x‘->T,对于x->y一条边,连x->y‘。X集合为点x,Y集合为点x‘
正确性:每条路径上的点度数最大为2。x点代表点x的出度,x‘点代表点x的入度。一条边会占用一个点的出度和另一个点的入度。对于每条路径,发现起点只有出度,没有入度,那么Y集合中没有被连的点就是某条路径的起点。于是n - 最大匹配 = 最小路径数
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <cmath> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 template <class T> 13 inline void swap(T& a, T& b) 14 { 15 T tmp = a;a = b;b = tmp; 16 } 17 inline void read(int &x) 18 { 19 x = 0;char ch = getchar(), c = ch; 20 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 21 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 22 if(c == ‘-‘) x = -x; 23 } 24 25 const int INF = 100000; 26 const int MAXN = 300 + 10; 27 const int MAXM = MAXN * MAXN; 28 29 struct Edge 30 { 31 int u,v,w,nxt; 32 Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;} 33 Edge(){} 34 }edge[MAXM << 1]; 35 int head[MAXN], cnt = 1; 36 inline void insert(int u, int v, int w) 37 { 38 edge[++cnt] = Edge(u,v,w,head[u]); 39 head[u] = cnt; 40 edge[++cnt] = Edge(v,u,0,head[v]); 41 head[v] = cnt; 42 } 43 44 int q[MAXN << 1], h[MAXN << 1], ans, S, T, he, ta, fa[MAXN << 1],vis[MAXN]; 45 std::vector<int> node[MAXN << 1]; 46 47 bool bfs() 48 { 49 int he = 0, ta = 1; 50 memset(h, -1, sizeof(h)); 51 q[he] = S, h[S] = 0; 52 while(he < ta) 53 { 54 int now = q[he ++]; 55 for(int pos = head[now];pos;pos = edge[pos].nxt) 56 { 57 int v = edge[pos].v; 58 if(h[v] == -1 && edge[pos].w) 59 { 60 h[v] = h[now] + 1; 61 q[ta ++] = v; 62 } 63 } 64 } 65 return h[T] != -1; 66 } 67 68 int dfs(int x, int f) 69 { 70 if(x == T) return f; 71 int w, used = 0; 72 for(int pos = head[x];pos;pos = edge[pos].nxt) 73 { 74 int v = edge[pos].v; 75 if(h[v] == h[x] + 1) 76 { 77 w = dfs(v, min(f - used, edge[pos].w)); 78 if(w) fa[x] = v, node[v].push_back(x); 79 edge[pos].w -= w; 80 edge[pos ^ 1].w += w; 81 used += w; 82 if(used == f) return f; 83 } 84 } 85 if(!used) h[x] = -1; 86 return used; 87 } 88 89 void dinic() 90 { 91 while(bfs()) ans += dfs(S, INF); 92 } 93 94 int n,m; 95 96 void dfs(int x) 97 { 98 vis[x] = 1; 99 printf("%d ", x); 100 if(fa[x]) dfs(fa[x] - n); 101 } 102 103 int main() 104 { 105 read(n), read(m); 106 S = n * 2 + 1, T = n * 2 + 2; 107 for(int i = 1;i <= n;++ i) insert(S, i, 1); 108 for(int i = 1;i <= m;++ i) 109 { 110 int tmp1,tmp2; 111 read(tmp1), read(tmp2); 112 insert(tmp1, tmp2 + n, 1); 113 } 114 for(int i = 1;i <= n;++ i) insert(i + n, T, 1); 115 dinic(); 116 for(int i = 1;i <= n;++ i) 117 if(fa[i]) 118 vis[fa[i] - n] = 1; 119 for(int i = 1;i <= n;++ i) 120 if(!vis[i]) 121 dfs(i), putchar(‘\n‘); 122 printf("%d", n - ans); 123 return 0; 124 }
04、魔术球问题
«问题描述:
假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。
«编程任务:
对于给定的n,计算在n根柱子上最多能放多少个球。
最小路径覆盖变种。二分放多少个球,如果x能放到y上面,就有x->y,答案即为图上的最小路径覆盖数。
发现二分放多少个求,还不如直接从1开始枚举放的求数,每多一个球加一个的边,跑一次增广。
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <queue> 8 #include <vector> 9 #include <cmath> 10 #define min(a, b) ((a) < (b) ? (a) : (b)) 11 #define max(a, b) ((a) > (b) ? (a) : (b)) 12 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 13 template <class T> 14 inline void swap(T& a, T& b) 15 { 16 T tmp = a;a = b;b = tmp; 17 } 18 inline void read(int &x) 19 { 20 x = 0;char ch = getchar(), c = ch; 21 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 22 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 23 if(c == ‘-‘) x = -x; 24 } 25 26 const int INF = 100000; 27 const int MAXN = 100000; 28 const int MAXM = 100000; 29 30 struct Edge 31 { 32 int u,v,w,nxt; 33 Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;} 34 Edge(){} 35 }edge[MAXM << 1]; 36 int head[MAXN << 1], cnt = 1, S, T, ans, fa[MAXN << 1], h[MAXN << 1], q[MAXN << 1], he, ta; 37 inline void insert(int a, int b, int c) 38 { 39 edge[++cnt] = Edge(a,b,c,head[a]); 40 head[a] = cnt; 41 edge[++cnt] = Edge(b,a,0,head[b]); 42 head[b] = cnt; 43 } 44 bool bfs() 45 { 46 memset(h, -1, sizeof(h)); 47 he = 0, ta = 1, q[0] = S, h[S] = 0; 48 while(he < ta) 49 { 50 int now = q[he ++]; 51 for(int pos = head[now];pos;pos = edge[pos].nxt) 52 { 53 int v = edge[pos].v; 54 if(h[v] == -1 && edge[pos].w) q[ta ++] = v, h[v] = h[now] + 1; 55 } 56 } 57 return h[T] != -1; 58 } 59 int dfs(int x, int f) 60 { 61 if(x == T) return f; 62 int used = 0, w; 63 for(int pos = head[x];pos;pos = edge[pos].nxt) 64 { 65 int v = edge[pos].v; 66 if(h[v] == h[x] + 1) 67 { 68 w = dfs(v, min(f - used, edge[pos].w)); 69 if(w) fa[x] = v; 70 edge[pos].w -= w; 71 edge[pos ^ 1].w += w; 72 used += w; 73 if(used == f) return f; 74 } 75 } 76 if(!used) h[x] = -1; 77 return used; 78 } 79 void Dinic() 80 { 81 while(bfs()) ans += dfs(S, INF); 82 } 83 84 int n, ma, vis[MAXN]; 85 86 void dfs(int x) 87 { 88 vis[x] = 1; 89 printf("%d ", x); 90 if(fa[x]) dfs(fa[x] - 2000); 91 } 92 93 int main() 94 { 95 read(n);S = 10000, T = S + 1; 96 for(ma = 1;;++ ma) 97 { 98 insert(S, ma, 1); insert(ma + 2000, T, 1); 99 for(int j = sqrt(ma) + 1;j * j - ma < ma;++ j) 100 insert(j * j - ma, ma + 2000, 1); 101 Dinic(); 102 if(ma - ans == n + 1) break; 103 } 104 -- ma; 105 printf("%d\n", ma); 106 memset(head, 0, sizeof(head)), cnt = 0, memset(fa, 0, sizeof(fa)), ans = 0; 107 for(int i = 1;i <= ma;++ i) 108 { 109 insert(S, i, 1); insert(i + 2000, T, 1); 110 int t = sqrt(i); 111 for(int j = sqrt(i) + 1;j * j - i < i;++ j) 112 insert(j * j - i, i + 2000, 1); 113 Dinic(); 114 } 115 for(int i = 1;i <= ma;++ i) 116 if(fa[i]) vis[fa[i] - 2000] = 1; 117 for(int i = 1;i <= ma;++ i) if(!vis[i]) dfs(i), putchar(‘\n‘); 118 return 0; 119 }
05、圆桌问题
假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri (i =1,2,……,m)。
会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,……,n)个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。
对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
有点裸
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <cmath> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 template <class T> 13 inline void swap(T& a, T& b) 14 { 15 T tmp = a;a = b;b = tmp; 16 } 17 inline void read(int &x) 18 { 19 x = 0;char ch = getchar(), c = ch; 20 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 21 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 22 if(c == ‘-‘) x = -x; 23 } 24 25 const int INF = 100000; 26 const int MAXN = 10000; 27 const int MAXM = 100000; 28 29 struct Edge 30 { 31 int u,v,w,nxt; 32 Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;} 33 Edge(){} 34 }edge[MAXM << 1]; 35 int head[MAXN << 1], cnt = 1, S, T, ans, h[MAXN << 1], q[MAXN << 1], he, ta; 36 inline void insert(int a, int b, int c) 37 { 38 edge[++cnt] = Edge(a,b,c,head[a]); 39 head[a] = cnt; 40 edge[++cnt] = Edge(b,a,0,head[b]); 41 head[b] = cnt; 42 } 43 bool bfs() 44 { 45 memset(h, -1, sizeof(h)); 46 he = 0, ta = 1, q[0] = S, h[S] = 0; 47 while(he < ta) 48 { 49 int now = q[he ++]; 50 for(int pos = head[now];pos;pos = edge[pos].nxt) 51 { 52 int v = edge[pos].v; 53 if(h[v] == -1 && edge[pos].w) 54 { 55 q[ta ++] = v, h[v] = h[now] + 1; 56 } 57 } 58 } 59 return h[T] != -1; 60 } 61 int dfs(int x, int f) 62 { 63 if(x == T) return f; 64 int used = 0, w; 65 for(int pos = head[x];pos;pos = edge[pos].nxt) 66 { 67 int v = edge[pos].v; 68 if(h[v] == h[x] + 1) 69 { 70 w = dfs(v, min(f - used, edge[pos].w)); 71 edge[pos].w -= w; 72 edge[pos ^ 1].w += w; 73 used += w; 74 if(used == f) return f; 75 } 76 } 77 if(!used) h[x] = -1; 78 return used; 79 } 80 void Dinic() 81 { 82 while(bfs()) ans += dfs(S, INF); 83 } 84 int n,m,tmp,sum,vis[MAXN]; 85 86 int main() 87 { 88 read(m), read(n); S = n + m + 1, T = S + 1; 89 for(int i = 1;i <= m;++ i) read(tmp), sum += tmp, insert(S, i, tmp); 90 for(int i = 1;i <= n;++ i) read(tmp), insert(i + m, T, tmp); 91 for(int i = 1;i <= m;++ i) 92 for(int j = 1;j <= n;++ j) 93 insert(i, j + m, 1); 94 Dinic(); 95 if(ans != sum){printf("0\n");return 0;} 96 printf("1"); 97 for(int i = 1;i <= m;++ i) 98 { 99 int flag = 1; 100 for(int pos = head[i];pos;pos = edge[pos].nxt) 101 if(edge[pos].v == S) continue; 102 else if(!edge[pos].w) 103 if(flag) printf("\n%d ", edge[pos].v - m), flag = 0; 104 else printf("%d ", edge[pos].v - m); 105 } 106 return 0; 107 }
06、最长不下降子序列问题
«问题描述:
给定正整数序列x1,...,xn 。
(1)计算其最长不下降子序列的长度s。
(2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列。
(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列。
«编程任务:
设计有效算法完成(1)(2)(3)提出的计算任务。
第一、二个问题都有nlogn解法,详见http://www.cnblogs.com/huibixiaoxing/p/7398826.html第三题
这里讨论网络流解法
第一问直接暴力dp即可,设答案为k
第二问,相当于每个点限流1,用最大流模拟转移,考虑拆点。对于点x,拆成x和x‘,x - > x‘,容量1, 对于i和j,i < j,若有s[j] >= s[i],就从i’ - > j,容量为1。对于f[i] = k的点i,连i‘ - > T,容量为1,可以证明每一个序列都可以通过一个流表示出来。跑最大流即可
第三问,相当于x1和xn可以取无数次,那就把x1->x1‘,xn->xn‘,S->x1‘,S->xn‘,xn‘->T(如果存在),x1‘->T(如果存在)改成正无穷即可
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <cmath> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 template <class T> 13 inline void swap(T& a, T& b) 14 { 15 T tmp = a;a = b;b = tmp; 16 } 17 inline void read(int &x) 18 { 19 x = 0;char ch = getchar(), c = ch; 20 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 21 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 22 if(c == ‘-‘) x = -x; 23 } 24 25 const int INF = 100000; 26 const int MAXN = 10000; 27 const int MAXM = 100000; 28 29 struct Edge 30 { 31 int u,v,w,nxt; 32 Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;} 33 Edge(){} 34 }edge[MAXM << 1]; 35 int head[MAXN << 1], cnt = 1, S, T, ans, h[MAXN << 1], q[MAXN << 1], he, ta; 36 inline void insert(int a, int b, int c) 37 { 38 edge[++cnt] = Edge(a,b,c,head[a]); 39 head[a] = cnt; 40 edge[++cnt] = Edge(b,a,0,head[b]); 41 head[b] = cnt; 42 } 43 bool bfs() 44 { 45 memset(h, -1, sizeof(h)); 46 he = 0, ta = 1, q[0] = S, h[S] = 0; 47 while(he < ta) 48 { 49 int now = q[he ++]; 50 for(int pos = head[now];pos;pos = edge[pos].nxt) 51 { 52 int v = edge[pos].v; 53 if(h[v] == -1 && edge[pos].w) 54 { 55 q[ta ++] = v, h[v] = h[now] + 1; 56 } 57 } 58 } 59 return h[T] != -1; 60 } 61 int dfs(int x, int f) 62 { 63 if(x == T) return f; 64 int used = 0, w; 65 for(int pos = head[x];pos;pos = edge[pos].nxt) 66 { 67 int v = edge[pos].v; 68 if(h[v] == h[x] + 1) 69 { 70 w = dfs(v, min(f - used, edge[pos].w)); 71 edge[pos].w -= w; 72 edge[pos ^ 1].w += w; 73 used += w; 74 if(used == f) return f; 75 } 76 } 77 if(!used) h[x] = -1; 78 return used; 79 } 80 void Dinic() 81 { 82 while(bfs()) ans += dfs(S, INF); 83 } 84 85 int n, f[MAXN], num[MAXN], ma; 86 87 int main() 88 { 89 read(n); 90 for(register int i = 1;i <= n;++ i) 91 { 92 insert(i, i + n, 1); 93 read(num[i]); 94 f[i] = 1; 95 for(register int j = 1;j < i;++ j) 96 if(num[j] <= num[i]) f[i] = max(f[i], f[j] + 1); 97 ma = max(ma, f[i]); 98 } 99 printf("%d\n", ma); 100 if(ma == 1) 101 { 102 printf("%d\n%d", n, n); 103 return 0; 104 } 105 S = n + n + 1, T = S + 1; 106 for(register int i = 1;i <= n;++ i) 107 if(f[i] == 1) insert(S, i, 1); 108 else if(f[i] == ma) insert(i + n, T, 1); 109 for(register int i = 1;i <= n;++ i) 110 for(register int j = 1;j < i;++ j) 111 if(num[j] <= num[i] && f[i] == f[j] + 1) 112 insert(j + n, i, 1); 113 Dinic(); 114 printf("%d\n", ans); 115 insert(1, n + 1, INF), insert(n, n + n, INF); 116 if(f[1] == 1) insert(S, 1, INF); 117 if(f[1] == ma) insert(1 + n, T, INF); 118 if(f[n] == 1) insert(S, n, INF); 119 if(f[n] == ma) insert(n + n, T, INF); 120 Dinic(); 121 printf("%d", ans); 122 return 0; 123 }
07、试题库问题
«问题描述:
假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m 道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算法。
«编程任务:
对于给定的组卷要求,计算满足要求的组卷方案。
有点裸
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <cmath> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 template <class T> 13 inline void swap(T& a, T& b) 14 { 15 T tmp = a;a = b;b = tmp; 16 } 17 inline void read(int &x) 18 { 19 x = 0;char ch = getchar(), c = ch; 20 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 21 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 22 if(c == ‘-‘) x = -x; 23 } 24 25 const int INF = 100000; 26 const int MAXN = 100000 + 10; 27 const int MAXM = 1000000 + 10; 28 29 struct Edge 30 { 31 int u,v,w,nxt; 32 Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;} 33 Edge(){} 34 }edge[MAXM << 1]; 35 int head[MAXN << 1], cnt = 1, S, T, ans, h[MAXN << 1], fa[MAXN << 1], q[MAXN << 1], he, ta; 36 inline void insert(int a, int b, int c) 37 { 38 edge[++ cnt] = Edge(a,b,c,head[a]); 39 head[a] = cnt; 40 edge[++ cnt] = Edge(b,a,0,head[b]); 41 head[b] = cnt; 42 } 43 bool bfs() 44 { 45 he = 0, ta = 1, q[he] = S, memset(h, -1, sizeof(h)), h[S] = 0; 46 while(he < ta) 47 { 48 int now = q[he ++]; 49 for(int pos = head[now];pos;pos = edge[pos].nxt) 50 { 51 int v = edge[pos].v; 52 if(h[v] == -1 && edge[pos].w) 53 h[v] = h[now] + 1, q[ta ++] = v; 54 } 55 } 56 return h[T] != -1; 57 } 58 int dfs(int x, int f) 59 { 60 if(x == T) return f; 61 int w,used = 0; 62 for(int pos = head[x];pos;pos = edge[pos].nxt) 63 { 64 int v = edge[pos].v; 65 if(h[v] == h[x] + 1) 66 { 67 w = dfs(v, min(f - used, edge[pos].w)); 68 edge[pos].w -= w; 69 edge[pos ^ 1].w += w; 70 if(w) fa[x] = v; 71 used += w; 72 if(used == f) return f; 73 } 74 } 75 if(!used) h[x] = -1; 76 return used; 77 } 78 void Dinic() 79 { 80 while(bfs()) ans += dfs(S, INF); 81 } 82 int k,n,tmp,tmp2,sum; 83 int main() 84 { 85 read(k), read(n); 86 S = n + k + 1, T = S + 1; 87 for(int i = 1;i <= n;++ i) insert(S, i, 1); 88 for(int i = 1;i <= k;++ i) read(tmp), sum += tmp, insert(n + i, T, tmp); 89 for(int i = 1;i <= n;++ i) 90 { 91 read(tmp); 92 for(int j = 1;j <= tmp;++ j) read(tmp2), insert(i, tmp2 + n, 1); 93 } 94 Dinic(); 95 if(ans != sum){printf("No Solution!\n");return 0;} 96 for(int i = 1;i <= k;++ i) 97 { 98 printf("%d: ", i); 99 for(int j = 1;j <= n;++ j) if(fa[j] == i + n) printf("%d ", j); 100 putchar(‘\n‘); 101 } 102 return 0; 103 }
08、机器人路径规划问题
机器人 Rob 可在一个树状路径上自由移动。给定树状路径 T 上的起点 s 和终点 t,机器人 Rob 要从 s 运动到 t。树状路径 T 上有若干可移动的障碍物。由于路径狭窄,任何时刻在路径的任何位置不能同时容纳 2 个物体。每一步可以将障碍物或机器人移到相邻的空顶点上。设计一个有效算法用最少移动次数使机器人从 s 运动到 t。对于给定的树 T,以及障碍物在树 T 中的分布情况。计算机器人从起点 s 到终点 t 的最少移动次数。
据说此题网络流不可做。其他做法也不太好,复杂度很高网络流24题:我们之中出了个叛徒!
09、方格取数问题
在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
看见方格就黑白染色。发现不能放在相邻的异色格子上。想到最小割。
对于白色格点(i,j),向黑色格点(i + 1, j)和(i,j + 1)连边,容量INF,S向白色格点连权值,黑色格点向T连权值,每一条S->T的路径都对应一个不满足条件的放法,因此要使得取出的数S->T不存在,割掉一条边意味着不取出这个方格中的数,求最小割即为留下的最少,取出的用总和减
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <queue> 8 #include <vector> 9 #include <cmath> 10 #define min(a, b) ((a) < (b) ? (a) : (b)) 11 #define max(a, b) ((a) > (b) ? (a) : (b)) 12 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 13 #define hao(a, b) ((a) * m + (b)) 14 template <class T> 15 inline void swap(T& a, T& b) 16 { 17 T tmp = a;a = b;b = tmp; 18 } 19 inline void read(int &x) 20 { 21 x = 0;char ch = getchar(), c = ch; 22 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 23 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 24 if(c == ‘-‘) x = -x; 25 } 26 27 const int INF = 100000; 28 const int MAXN = 100000 + 10; 29 const int MAXM = 1000000 + 10; 30 31 struct Edge 32 { 33 int u,v,w,nxt; 34 Edge(int _u, int _v, int _w, int _nxt){u = _u, v = _v, w = _w, nxt = _nxt;} 35 Edge(){} 36 }edge[MAXM << 1]; 37 int head[MAXN << 1], cnt = 1, q[MAXN << 1], h[MAXN << 1], S, T, ans, he, ta; 38 inline void insert(int a, int b, int c) 39 { 40 edge[++cnt] = Edge(a,b,c,head[a]); 41 head[a] = cnt; 42 edge[++cnt] = Edge(b,a,0,head[b]); 43 head[b] = cnt; 44 } 45 bool bfs() 46 { 47 memset(h, -1, sizeof(h)), he = 0, ta = 1, q[0] = S, h[S] = 0; 48 while(he < ta) 49 { 50 int now = q[he ++]; 51 for(int pos = head[now];pos;pos = edge[pos].nxt) 52 { 53 int v = edge[pos].v; 54 if(h[v] == -1 && edge[pos].w) 55 h[v] = h[now] + 1, q[ta ++] = v; 56 } 57 } 58 return h[T] != -1; 59 } 60 int dfs(int x, int f) 61 { 62 if(x == T) return f; 63 int used = 0, w; 64 for(int pos = head[x];pos;pos = edge[pos].nxt) 65 { 66 int v = edge[pos].v; 67 if(h[v] == h[x] + 1) 68 { 69 w = dfs(v, min(f - used, edge[pos].w)); 70 edge[pos].w -= w; 71 edge[pos ^ 1].w += w; 72 used += w; 73 if(used == f) return f; 74 } 75 } 76 if(!used) h[x] = -1; 77 return used; 78 } 79 void Dinic() 80 { 81 while(bfs()) ans += dfs(S, INF); 82 } 83 84 int n,m,g[150][150],sum; 85 86 int main() 87 { 88 read(n), read(m); 89 S = hao(n, m) + 1, T = S + 1; 90 for(int i = 1;i <= n;++ i) 91 for(int j = 1;j <= m;++ j) 92 { 93 int tmp; read(tmp);sum += tmp; 94 if((i + j) & 1) 95 { 96 insert(S, hao(i, j), tmp); 97 if(i + 1 <= n) insert(hao(i, j), hao(i + 1, j), INF); 98 if(j + 1 <= m) insert(hao(i, j), hao(i, j + 1), INF); 99 } 100 else 101 { 102 insert(hao(i, j), T, tmp); 103 if(i + 1 <= n) insert(hao(i + 1, j), hao(i, j), INF); 104 if(j + 1 <= m) insert(hao(i, j + 1), hao(i, j), INF); 105 } 106 } 107 Dinic(); 108 printf("%d", sum - ans); 109 return 0; 110 }
10、餐巾计划问题
一个餐厅在相继的 NNN 天里,每天需用的餐巾数不尽相同。假设第 iii 天需要 rir_iri?块餐巾( i=1,2,...,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 ppp 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 nnn 天(n>mn>mn>m),其费用为 sss 分(s<fs<fs<f)。
每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。
试设计一个算法为餐厅合理地安排好 NNN 天中餐巾使用计划,使总的花费最小。编程找出一个最佳餐巾使用计划。
每天拆成两个点x(X集合),x(Y集合)‘,x表示第x天用完剩下的餐巾,x‘表示第x天要用的餐巾,让x‘连向T,容量为当天需要的餐巾数,把S连向x,容量为当天需要的餐巾数,考虑如何用X集合补满Y集合的流。
对于购买,从S连向Y集合,容量+∞,费用p
对于快洗,x->x + m,容量+∞,费用f
对于慢洗,x->x + nnn,容量+∞,费用sss
还有可能上一天的餐巾留到下一天,从x -> x + 1容量+∞,费用0(容易漏掉)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <cmath> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 template <class T> 13 inline void swap(T& a, T& b) 14 { 15 T tmp = a;a = b;b = tmp; 16 } 17 inline void read(long long &x) 18 { 19 x = 0;char ch = getchar(), c = ch; 20 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 21 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 22 if(c == ‘-‘) x = -x; 23 } 24 25 const long long INF = 0x3f3f3f3f3f3f3f3f; 26 const long long MAXN = 200000 + 10; 27 const long long MAXM = 1000000 + 10; 28 29 struct Edge 30 { 31 long long u,v,w,c,nxt; 32 Edge(long long _u, long long _v, long long _w, long long _c, long long _nxt){u = _u;v = _v;w = _w;c = _c;nxt = _nxt;} 33 Edge(){} 34 }edge[MAXN << 1]; 35 long long head[MAXN << 1], cnt = 1, q[MAXN << 1], he, ta, d[MAXN << 1], b[MAXN << 1], from[MAXN << 1], S, T, ans, nn; 36 inline void insert(long long a, long long b, long long c, long long d) 37 { 38 edge[++cnt] = Edge(a,b,c,d,head[a]); 39 head[a] = cnt; 40 edge[++cnt] = Edge(b,a,0,-d,head[b]); 41 head[b] = cnt; 42 } 43 bool bfs() 44 { 45 he = 0, ta = 1, memset(d, 0x3f3f3f3f, sizeof(d)), d[S] = 0, b[S] = 1, q[0] = S; 46 while(he < ta) 47 { 48 long long now = q[he ++]; 49 if(he > MAXN) he = 0; 50 for(long long pos = head[now];pos;pos = edge[pos].nxt) 51 { 52 long long v = edge[pos].v; 53 if(edge[pos].w && d[v] > d[now] + edge[pos].c) 54 { 55 d[v] = d[now] + edge[pos].c, from[v] = pos; 56 if(!b[v]) 57 { 58 b[v] = 1, q[ta ++] = v; 59 if(ta > MAXN) ta = 0; 60 } 61 } 62 } 63 b[now] = 0; 64 } 65 return d[T] != INF; 66 } 67 void flow() 68 { 69 long long x = INF; 70 for(long long i = from[T];i;i = from[edge[i].u]) x = min(x, edge[i].w); 71 for(long long i = from[T];i;i = from[edge[i].u]) edge[i].w -= x, edge[i ^ 1].w += x, ans += edge[i].c * x; 72 } 73 void mcf() 74 { 75 while(bfs()) 76 flow(); 77 } 78 79 long long num[MAXN],p,m,f,n,s; 80 81 int main() 82 { 83 read(nn);S = nn + nn + 1, T = S + 1; 84 for(long long i = 1;i <= nn;++ i) read(num[i]); 85 read(p), read(m), read(f), read(n), read(s); 86 for(long long i = 1;i <= nn;++ i) 87 insert(S, i, num[i], 0); 88 for(long long i = 1;i < nn;++ i) 89 insert(i, i + 1, INF, 0); 90 for(long long i = 1;i <= nn - m;++ i) 91 insert(i, i + m + nn, INF, f); 92 for(long long i = 1;i <= nn - n;++ i) 93 insert(i, i + n + nn, INF, s); 94 for(long long i = 1;i <= nn;++ i) 95 insert(S, i + nn, INF, p); 96 for(long long i = 1;i <= nn;++ i) 97 insert(i + nn, T, num[i], 0); 98 mcf(); 99 printf("%lld", ans); 100 101 return 0; 102 }
11、航空路线问题
给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。
(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市)。
(2)除起点城市外,任何城市只能访问 1 次。
对于给定的航空图,试设计一个算法找出一条满足要求的最佳航空旅行路线。
直接想成从起点到终点,找两条不相交最长路径即可
每个点限流一次,还是考虑拆点x,x‘,x - > x‘容量为1,费用为0,特别的起点和终点可以流两次,S - S‘和T - > T‘,容量为2,费用为0
对于a -> b,连a‘ -> b,容量为1,费用为1(环上点数等于边数)
求最大费用最大流即可
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <map> 9 #include <string> 10 #include <cmath> 11 #define min(a, b) ((a) < (b) ? (a) : (b)) 12 #define max(a, b) ((a) > (b) ? (a) : (b)) 13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 14 template <class T> 15 inline void swap(T& a, T& b) 16 { 17 T tmp = a;a = b;b = tmp; 18 } 19 inline void read(int &x) 20 { 21 x = 0;char ch = getchar(), c = ch; 22 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 23 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 24 if(c == ‘-‘) x = -x; 25 } 26 27 const int INF = 0x3f3f3f3f; 28 const int MAXN = 100000 + 10; 29 const int MAXM = 1000000 + 10; 30 31 struct Edge 32 { 33 int u,v,w,c,nxt; 34 Edge(int _u, int _v, int _w, int _c, int _nxt){u = _u;v = _v;w = _w;c = _c;nxt = _nxt;} 35 Edge(){} 36 }edge[MAXM << 1]; 37 int head[MAXN << 1], he, ta, cnt = 1, ans, anss, q[MAXN << 1], from[MAXN << 1], d[MAXN << 1], b[MAXN << 1], S, T; 38 void insert(int a, int b, int c, int d) 39 { 40 edge[++cnt] = Edge(a,b,c,d,head[a]); head[a] = cnt; 41 edge[++cnt] = Edge(b,a,0,-d,head[b]); head[b] = cnt; 42 } 43 bool spfa() 44 { 45 memset(d, 0x3f, sizeof(d)); 46 int he = 0, ta = 1; 47 d[S] = 0, b[S] = 1, q[he] = S; 48 while(he != ta) 49 { 50 int now = q[he ++]; 51 if(he > MAXN) he = 0; 52 for(int pos = head[now];pos;pos = edge[pos].nxt) 53 if(edge[pos].w && d[edge[pos].v] > d[now] + edge[pos].c) 54 { 55 d[edge[pos].v] = d[now] + edge[pos].c; 56 from[edge[pos].v] = pos; 57 if(!b[edge[pos].v]) 58 { 59 b[edge[pos].v]=1; 60 q[ta ++] = edge[pos].v; 61 if(ta > MAXN)ta = 0; 62 } 63 } 64 b[now] = 0; 65 } 66 if(d[T] == INF)return 0; 67 return 1; 68 } 69 70 void flow() 71 { 72 int x = INF; 73 for(int i = from[T];i;i = from[edge[i].u]) 74 x = min(x, edge[i].w); 75 for(int i = from[T];i;i = from[edge[i].u]) 76 { 77 edge[i].w -= x; 78 edge[i^1].w += x; 79 ans += edge[i].c * x; 80 } 81 anss += x; 82 } 83 84 void mcf() 85 { 86 while(spfa()) flow(); 87 } 88 89 int n,m,vis[MAXN]; 90 std::string s[MAXN]; 91 std::map<std::string, int> mp; 92 93 void dfs(int x) 94 { 95 if(x == n) return; 96 vis[x] = 1; 97 std::cout << s[x] << std::endl; 98 x += n; 99 for(int pos = head[x];pos;pos = edge[pos].nxt) 100 { 101 int v = edge[pos].v; 102 if(v > n || vis[v] || edge[pos].w) continue; 103 dfs(v);return; 104 } 105 } 106 void redfs(int x) 107 { 108 vis[x] = 1; 109 if(x == n) 110 { 111 std::cout << s[n] << std::endl; 112 return; 113 } 114 x += n; 115 for(int pos = head[x];pos;pos = edge[pos].nxt) 116 { 117 int v = edge[pos].v; 118 if(v > n || vis[v] || edge[pos].w) continue; 119 redfs(v);break; 120 } 121 std::cout << s[x - n] << std::endl; 122 } 123 124 int main() 125 { 126 read(n), read(m);S = 1, T = n + n; 127 for(int i = 1;i <= n;++ i) 128 { 129 std::cin >> s[i]; 130 mp[s[i]] = i; 131 } 132 insert(1, 1 + n, 2, 0); 133 insert(n, n + n, 2, 0); 134 for(int i = 2;i < n;++ i) 135 insert(i, i + n, 1, 0); 136 for(int i = 1;i <= m;++ i) 137 { 138 std::string tmp1,tmp2; 139 std::cin >> tmp1 >> tmp2; 140 int ma1, ma2; 141 ma1 = mp[tmp1], ma2 = mp[tmp2]; 142 if(ma1 > ma2) swap(ma1, ma2); 143 if(ma1 == 1 && ma2 == n) insert(ma1 + n, ma2, 2, -1); 144 else insert(ma1 + n, ma2, 1, -1); 145 } 146 mcf(); 147 if(anss != 2) printf("No Solution!\n"); 148 else 149 { 150 printf("%d\n", -ans); 151 dfs(1); 152 redfs(1); 153 } 154 return 0; 155 }
(未完待续.....)