• 【线性规划与网络流 24题】已完成(3道题因为某些奇怪的原因被抛弃了QAQ)


    写在前面:SDOI2016 Round1滚粗后蒟蒻开始做网络流来自我拯救(2016-04-11再过几天就要考先修课,现在做网络流24题貌似没什么用←退役节奏)

    做的题目将附上日期,见证我龟速刷题。

    1.飞行员配对方案问题 2016-04-11


      二分图最大匹配问题,更新了一下$Dinic$模板,带上了当前弧优化和多路增广。这道题输出方案有很多种,可是没有special judge,所以没有A,但方案数是对的。合法的输出方案只能用匈牙利算法解决。

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 1003;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    queue<int> q;
    bool vis[N];
    int point[N], cap[N], nxt[N], to[N], d[N], cur[N], S, T, cnt = 1;
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); d[S] = 0; vis[S] = 1;
    	int u, i;
    	while (!q.empty()) {
    		u = q.front(); q.pop();
    		for(i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int f, flow = 0;
    	for(int &i = cur[u]; i; i = nxt[i])
    		if (d[u] + 1 == d[to[i]] && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int flow = 0, i;
    	while (BFS()) {
    		for(i = 1; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, 0x7fffffff);
    	}
    	return flow;
    }
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    void findpair(int x) {
    	for(int i = point[x]; i; i = nxt[i])
    		if (cap[i] == 0 && to[i] != S) {printf("%d %d
    ", x, to[i]); break;}
    }
    int main() {
    	int n, m;
    	read(n); read(m);
    	S = n + m + 1; T = S + 1;
    	for(int i = 1; i <= n; ++i)
    		ins(S, i, 1), ins(i, S, 0);
    	for(int i = n + 1; i <= n + m; ++i)
    		ins(i, T, 1), ins(T, i, 0);
    	int u, v;
    	read(u); read(v);
    	while (u != -1 && v != -1) {
    		ins(u, v, 1); ins(v, u, 0);
    		read(u); read(v);
    	}
    	printf("%d
    ", Dinic());
    	for(int i = 1; i <= n; ++i)
    		findpair(i);
    	return 0;
    }
    

    2.太空飞行计划问题 2016-04-13


      典型的最大权闭合图问题,可是还是要输出方案!!!制杖地卡了1h+因为把n+m打成了n+m+1,然后发现还是会WA两个点。最后百度得知数据是不盈利也不亏损的项目还要加上,如果要这么做还得删边balabalabala。我不想再改了,所以就这样吧。我现在感觉什么都需要special judge,因为我太弱了hhh

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 1003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    bool vis[N];
    queue <int> q;
    int point[N], nxt[N], to[N], cap[N], d[N], cur[N], S, T, cnt = 1, n, m, Qsum = 0, Qmincut;
    
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); vis[S] = 1; d[S] = 0;
    	int u, i;
    	while (!q.empty()) {
    		u = q.front(); q.pop();
    		for(i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				q.push(to[i]);
    				vis[to[i]] = 1;
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int f, flow = 0;
    	for(int &i = cur[u]; i; i = nxt[i])
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int flow = 0, i;
    	while (BFS()) {
    		for(i = 1; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, inf);
    	}
    	return flow;
    }
    
    void Q() {
    	for(int i = 1; i <= m; ++i)
    		if (vis[i]) printf("%d ", i);
    	puts("");
    	
    	for(int i = m + 1; i <= m + n; ++i)
    		if (vis[i]) printf("%d ", i - m);
    	
    	printf("
    %d
    ", Qsum - Qmincut);
    }
    
    int main() {
    	read(m); read(n);
    	S = m + n + 1; T = S + 1;
    	
    	int num; char c;
    	for(int i = 1; i <= m; ++i) {
    		read(num);
    		Qsum += num;
    		ins(S, i, num);
    		ins(i, S, 0);
    		c = getchar();
    		while(1) {
    			num = 0;
    			for(; c < '0' || c > '9'; c = getchar())
    				if (c == '
    ') break;
    			if (c == '
    ') break;
    			for(; c >= '0' && c <= '9'; c = getchar())
    				num = num * 10 + c - '0';
    			num = num + m;
    			ins(i, num, inf);
    			ins(num, i, 0);
    		}
    	}
    	
    	for(int i = m + 1; i <= m + n; ++i) {
    		read(num);
    		ins(i, T, num);
    		ins(T, i, 0);
    	}
    	
    	Qmincut = Dinic();
    	
    	Q();
    	
    	return 0;
    }
    

    3.最小路径覆盖问题 2016-04-13


      二分图最大匹配问题。遇到求“最小”,因为我们求的都是最大流,所以应该往补集转化的方向思考,“总的”-“最大的”=“最小的”。这种题还应该注意一个地方,虽然在这里用不着,但要处处留心:最小路径覆盖问题值得注意的地方

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 20003;
    const int inf = 0x7fffffff;
    
    queue <int> q;
    bool vis[N];
    int point[N], cur[N], nxt[N], to[N], cap[N], d[N], n, m, S, T, cnt = 1, Qmincut;
    
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); d[S] = 0; vis[S] = 1;
    	while (!q.empty()) {
    		int u = q.front(), i; q.pop();
    		for(i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int f, flow = 0;
    	for(int &i = point[u]; i; i = nxt[i])
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int i, flow = 0;
    	while (BFS()) {
    		for(i = 1; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, inf);
    	}
    	return flow;
    }
    
    void QQ(int x) {
    	vis[x] = 1;
    	printf("%d ", x);
    	for(int i = point[x]; i; i = nxt[i])
    		if (cap[i] < inf && n < to[i] && to[i] <= n + n) QQ(to[i] - n);
    }
    void Q() {
    	memset(vis, 0, sizeof(vis));
    	for(int i = 1; i <= n; ++i)
    		if (!vis[i]) QQ(i), puts("");
    	printf("%d
    ", n - Qmincut);
    }
    int main() {
    	read(n); read(m);
    	int u, v;
    	S = n + n + 1; T = S + 1;
    	for(int i = 1, j = n + 1; i <= n; ++i, ++j)
    		ins(S, i, 1), ins(i, S, 0), ins(j, T, 1), ins(T, j, 0);
    	for(int i = 1; i <= m; ++i) {
    		read(u); read(v); v += n;
    		ins(u, v, inf); ins(v, u, 0);
    	}
    	
    	Qmincut = Dinic();
    	
    	Q();
    	
    	return 0;
    }

    4.魔术球问题 2016-04-17


      最小路径覆盖问题,想了好久,看完题解后还是想了好久QuQ。当时主要是不明白为什么满足单调性,后来才发现DAG上不断加边,最小路径覆盖数肯定是不减的,当时好制杖啊QAQ。写完后更制杖的是我发现我又需要special judge!!!怎么我现在弱到什么都需要special judge!!!PS:昨天北大先修课乙烷,xyx考得最好但是他没有用正规的比赛号交题,,,

    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c= getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], nxt[N << 1], to[N << 1], cap[N << 1], d[N], S, T, cnt = 1, ans = 0, n, Q = 0;
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int f, flow = 0;
    	for(int i = point[u]; i; i = nxt[i])
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    void Dinic() {
    	while (BFS()) ans -= DFS(S, 0x7fffffff);
    }
    
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    void Qwork(int x) {
    	printf("%d ", x);
    	vis[x] = 1;
    	for(int i = point[x]; i; i = nxt[i])
    		if (!cap[i] &&  to[i] > 5000 && to[i] < 5000 + Q && !vis[to[i] - 5000])
    			Qwork(to[i] - 5000);
    }
    int main() {
    	read(n); S = 0; T = 10002;
    	while (1) {
    		++ans; ++Q;
    		for(int i = 1; i < Q; ++i)
    			if (sqrt(i + Q) == (int)(sqrt(i + Q)))
    				ins(i, Q + 5000, 1), ins(Q + 5000, i, 0);
    		ins(S, Q, 1); ins(Q, S, 0);
    		ins(Q + 5000, T, 1); ins(T, Q + 5000, 0);
    		Dinic();
    		if (ans > n) {
    			printf("%d
    ", Q - 1);
    			break;
    		}
    	}
    	
    	memset(vis, 0, sizeof(vis));
    	for(int i = 1; i < Q; ++i)
    		if (!vis[i])
    			Qwork(i), puts("");
    	
    	return 0;
    }

    5.圆桌问题 2016-04-17


      很简单的二分图多重匹配,写完后我发现我又需要special judge了QAQ

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], cur[N], nxt[N << 1], to[N << 1], cap[N << 1], S, T, cnt = 1, d[N];
    
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int f, flow = 0;
    	for(int &i = cur[u]; i; i = nxt[i])
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int flow = 0;
    	while (BFS()) {
    		for(int i = 0; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, 0x7fffffff);
    	}
    	return flow;
    }
    
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    int main() {
    	int n, m, x, Qsum = 0;
    	read(m); read(n);
    	S = 0; T = m + n + 1;
    	for(int i = 1; i <= m; ++i)
    		read(x), ins(S, i, x), ins(i, S, 0), Qsum += x;
    	for(int i = m + 1; i < T; ++i)
    		read(x), ins(i, T, x), ins(T, i, 0);
    	for(int i = 1; i <= m; ++i)
    		for(int j = m + 1; j < T; ++j)
    			ins(i, j, 1), ins(j, i, 0);
    	
    	int Q = Dinic();
    	if (Q == Qsum) {
    		puts("1");
    		for(int i = 1; i <= m; ++i) {
    			cnt = 0;
    			for(int tmp = point[i]; tmp; tmp = nxt[tmp])
    				if (!cap[tmp] && to[tmp] > m && to[tmp] < T)
    					d[++cnt] = to[tmp] - m;
    			for(; cnt; --cnt) printf("%d ", d[cnt]);
    			puts("");
    		}
    	} else
    		puts("0");
    	
    	return 0;
    }

    6.最长递增子序列问题 2016-04-17


      分层图思想可以保证走的每条路都是最长的,统计最大流就可以了,对于第三问放宽$X_1,X_n$的限制即可。还有一个地方我卡了好久,就是$inf$设置成了$0x7fffffff$,这样会出现爆int的情况,只需把inf调小一点,输出时特判一下就没了,,,TwT我卡了3h+啊

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x = getint()
    using namespace std;
    const int N = 100003;
    const int inf = 1E9;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], cur[N], d[N], nxt[N << 1], to[N << 1], cap[N << 1], S, T, cnt = 1;
    
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); d[S] = 0; vis[S] = 1;
    	while (!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int f, flow = 0;
    	for(int &i = cur[u]; i; i = nxt[i])
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int i, flow = 0;
    	while (BFS()) {
    		for(i = 0; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, inf);
    	}
    	return flow;
    }
    
    int a[N], f[N];
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    int main() {
    	int n;
    	read(n);
    	for(int i = 1; i <= n; ++i)
    		read(a[i]);
    	
    	f[n] = 1;
    	for(int i = n - 1; i > 0; --i) {
    		f[i] = 1;
    		for(int j = n; j > i; --j)
    			if (a[i] <= a[j] && f[j] + 1 > f[i])
    				f[i] = f[j] + 1;
    	}
    	
    	int k = 0;
    	for(int i = 1; i <= n; ++i)
    		k = max(k, f[i]);
    	printf("%d
    ", k);
    	
    	S = 0; T = (n << 1) + 1;
    	for(int i = 1; i <= n; ++i) {
    		ins(i, i + n, 1), ins(i + n, i, 0);
    		if (f[i] == k)
    			ins(S, i, 1), ins(i, S, 0);
    		if (f[i] == 1)
    			ins(i + n, T, 1), ins(T, i + n, 0);
    	}
    	for(int i = 1; i < n; ++i)
    		for(int j = i + 1; j <= n; ++j)
    			if (a[i] <= a[j] && f[i] == f[j] + 1)
    				ins(i + n, j, 1), ins(j, i + n, 0);
    	int Q = Dinic();
    	printf("%d
    ", Q);
    	
    	memset(point, 0, sizeof(point)); cnt = 1;
    	for(int i = 1; i <= n; ++i) {
    		if (i == 1 || i == n) {
    			ins(i, i + n, inf), ins(i + n, i, 0);
    			if (f[i] == k)
    				ins(S, i, inf), ins(i, S, 0);
    			if (f[i] == 1)
    				ins(i + n, T, inf), ins(T, i + n, 0);
    		} else {
    			ins(i, i + n, 1), ins(i + n, i, 0);
    			if (f[i] == k)
    				ins(S, i, 1), ins(i, S, 0);
    			if (f[i] == 1)
    				ins(i + n, T, 1), ins(T, i + n, 0);
    		}
    	}
    	for(int i = 1; i < n; ++i)
    		for(int j = i + 1; j <= n; ++j)
    			if (a[i] <= a[j] && f[i] == f[j] + 1)
    				ins(i + n, j, 1), ins(j, i + n, 0);
    	Q = Dinic();
    	printf("%d
    ", Q > inf ? n : Q);
    	
    	return 0;
    }

    7.试题库问题 2016-04-17


      水题,不过我又需要special judge了QuQ

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 10003;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], cur[N], nxt[N << 1], to[N << 1], S, T, cnt = 1, d[N], cap[N << 1];
    
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); d[S] = 0; vis[S] = 1;
    	while (!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int flow = 0, f;
    	for(int &i = cur[u]; i; i = nxt[i])
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int flow = 0;
    	while (BFS()) {
    		for(int i = 0; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, 0x7fffffff);
    	}
    	return flow;
    }
    
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    int main() {
    	int k, n, m = 0, x, p;
    	read(k); read(n);
    	S = 0; T = k + n + 1;
    	for(int i = 1; i <= k; ++i)
    		read(x), ins(S, i, x), ins(i, S, 0), m += x;
    	for(int i = 1; i <= n; ++i) {
    		read(p);
    		for(int j = 1; j <= p; ++j) {
    			read(x);
    			ins(x, i + k, 1);
    			ins(i + k, x, 0);
    		}
    	}
    	for(int i = k + 1; i < T; ++i)
    		ins(i, T, 1), ins(T, i, 0);
    	
    	int Q = Dinic();
    	if (Q == m) {
    		for(int i = 1; i <= k; ++i) {
    			printf("%d:", i);
    			for(int tmp = point[i]; tmp; tmp = nxt[tmp])
    				if (!cap[tmp] && to[tmp] > k && to[tmp] < T)
    					printf(" %d", to[tmp] - k);
    			puts("");
    		}
    	} else
    		puts("No Solution!");
    	
    	return 0;
    }

    8.机器人路径规划问题


      貌似这道题挺麻烦,CTSC和省选Round2前没有太多时间,暂时略过,省选二轮滚粗后再来看QAQ

    9.方格取数问题 2016-04-18


      因为最大独立点集+最小点覆盖集=总点数,那么最大点权独立集+最小点权覆盖集=总点权和。我们只需求最小点权覆盖集就可以了。

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int inf = 0x7fffffff;
    const int N = 100003;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], cur[N], nxt[N << 1], cap[N << 1], to[N << 1], S, T, cnt = 1, d[N];
    
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int flow = 0, f;
    	for(int &i = cur[u]; i; i = nxt[i])
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int flow = 0;
    	while (BFS()) {
    		for(int i = 0; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, inf);
    	}
    	return flow;
    }
    
    int a[53][53];
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    void QQ(int Qsum) {
    	int Q = Dinic();
    	Q = Qsum - Q;
    	printf("%d
    ", Q);
    }
    int main() {
    	int n, m, Qsum = 0;
    	read(m); read(n);
    	for(int i = 1; i <= m; ++i)
    		for(int j = 1; j <= n; ++j)
    			read(a[i][j]), Qsum += a[i][j];
    	S = 0; T = n * m + 1;
    	for(int i = 1; i <= m; ++i)
    		for(int j = 1; j <= n; ++j)
    			if ((i + j) % 2 == 0) {
    				ins(S, (i - 1) * n + j, a[i][j]);
    				ins((i - 1) * m + j, S, 0);
    				if (i > 1) {
    					ins((i - 1) * n + j, (i - 2) * n + j, inf);
    					ins((i - 2) * n + j, (i - 1) * n + j, 0);
    				}
    				if (j > 1) {
    					ins((i - 1) * n + j, (i - 1) * n + j - 1, inf);
    					ins((i - 1) * n + j - 1, (i - 1) * n + j, 0);
    				}
    				if (i < m) {
    					ins((i - 1) * n + j, i * n + j, inf);
    					ins(i * n + j, (i - 1) * n + j, 0);
    				}
    				if (j < n) {
    					ins((i - 1) * n + j, (i - 1) * n + j + 1, inf);
    					ins((i - 1) * n + j + 1, (i - 1) * n + j, 0);
    				}
    			}
    	for(int i = 1; i <= m; ++i)
    		for(int j = 1; j <= n; ++j)
    			if ((i + j) % 2 == 1) {
    				ins((i - 1) * n + j, T, a[i][j]);
    				ins(T, (i - 1) * n + j, 0);
    			}
    	
    	QQ(Qsum);
    	
    	return 0;
    }
    

    10.餐巾计划问题 2016-04-18


      最小费用最大流问题。在保证最大流的前提下求最小费用,建图我就不细说了,主要是把买的和洗的餐巾分为两部分,网上有很多题解。

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], nxt[N << 1], to[N << 1], cap[N << 1], S, T, cnt = 1;
    int d[N], w[N << 1], from[N << 1], pre[N << 1];
    
    bool spfa(int s, int t) {
    	for(int i = 0; i <= t; ++i) vis[i] = 0, d[i] = inf;
    	d[s] = 0; q.push(s);
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[t] != inf;
    }
    int mcmf(int s, int t) {
    	int ret = 0, f, u;
    	while (spfa(s, t)) {
    		f = inf;
    		for(u = t; u != s; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = t; u != s; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += f * d[t];
    	}
    	return ret;
    }
    
    int nn, p, m, f, n, s, r[N];
    void ins(int x, int y, int z, int zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    int main() {
    	read(nn); read(p); read(m); read(f); read(n); read(s);
    	for(int i = 1; i <= nn; ++i)
    		read(r[i]);
    	S = 0; T = (nn << 1) + 1;
    	for(int i = 1; i <= nn; ++i) {
    		ins(S, i, r[i], 0);
    		ins(i, S, 0, 0);
    		ins(i + nn, T, r[i], 0);
    		ins(T, i + nn, 0, 0);
    		ins(S, i + nn, inf, p);
    		ins(i + nn, S, 0, -p);
    		if (i < nn) {
    			ins(i, i + 1, inf, 0);
    			ins(i + 1, i, 0, 0);
    		}
    		if (i + m <= nn) {
    			ins(i, i + m + nn, inf, f);
    			ins(i + m + nn, i, 0, -f);
    		}
    		if (i + n <= nn) {
    			ins(i, i + n + nn, inf, s);
    			ins(i + n + nn, i, 0, -s);
    		}
    	}
    	
    	int Q = mcmf(S, T);
    	printf("%d
    ", Q);
    	
    	return 0;
    }
    

    11.航空路线问题 2016-04-18


      裸拆点最小费用最大流,我打错了MCMF模板,查了1h的错TwT。在第二组数据吐血QAQ,只好面向数据编程,,,还有I need special judge again!!!

    #include<map>
    #include<queue>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    map <string, int> ma;
    queue <int> q;
    bool vis[N];
    int point[N], nxt[N << 1], to[N << 1], cap[N << 1], d[N];
    int S, T, cnt = 1, w[N << 1], from[N << 1], pre[N];
    
    bool spfa() {
    	for(int i = 0; i <= T; ++i) vis[i] = 0, d[i] = inf;
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[T] != inf;
    }
    int mcmf() {
    	int ret = 0, f, u;
    	while (spfa()) {
    		f = inf;
    		for(u = T; u != S; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = T; u != S; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += f * d[T];
    	}
    	return ret;
    }
    
    int n, v, x, y;
    string s1, s2, str[N];
    void ins(int x, int y, int z, int zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    void QQ(int x) {
    	cout<< str[x] << endl;
    	for(int i = point[x + n]; i; i = nxt[i])
    		if (!cap[i] && !vis[to[i]] && to[i] > 0 && to[i] <= n)
    			{QQ(to[i]); break;}
    }
    void QQQ(int x) {
    	if (x == n) {
    		QQ(1);
    		return;
    	}
    	vis[x] = 1;
    	for(int i = point[x + n]; i; i = nxt[i])
    		if (!cap[i] && to[i] > 0 && to[i] <= n)
    			{QQQ(to[i]); break;}
    	cout << str[x] <<endl;
    }
    int main() {
    	read(n); read(v);
    	ma.clear();
    	for(int i = 1; i <= n; ++i)
    		cin >> str[i], ma[str[i]] = i;
    	S = 1; T = n << 1;
    	for(int i = 1; i <= n; ++i)
    		if (i == 1 || i == n) {
    			ins(i, i + n, 2, -1);
    			ins(i + n, i, 0, 1);
    		} else {
    			ins(i, i + n, 1, -1);
    			ins(i + n, i, 0, 1);
    		}
    	for(int i = 1; i <= v; ++i) {
    		cin >> s1 >> s2;
    		x = ma[s1]; y = ma[s2];
    		ins(x + n, y, 1, 0);
    		ins(y, x + n, 0, 0);
    	}
    	
    	int Q = mcmf();
    	if (cap[2] && n != 3)
    		puts("No Solution!");
    	else
    		printf("%d
    ", n != 3 ? - Q - 2 : -Q), memset(vis, 0, sizeof(vis)), QQQ(1);
    	
    	return 0;
    }
    

    12.软件补丁问题 2016-04-18


      因为只有20种错误,考虑状态压缩然后spfa最短路,这还是网络流吗,,,

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 2000003;
    char a[23], b[23];
    bool vis[N];
    queue <int> q;
    int b1[N], b2[N], f1[N], f2[N], cost[N], n, m, d[N], inf;
    int spfa(int s, int t) {
    	memset(d, 127, sizeof(d)); inf = d[t];
    	d[s] = 0; q.push(s); vis[s] = 0;
    	
    	while (!q.empty()) {
    		int x = q.front(); q.pop(); vis[x] = 0;
    		for(int i = 1; i <= m; ++i)
    			if ((x | b1[i]) == x && (x & b2[i]) == 0) {
    				int y = x & (~ f1[i]);
    				y |= f2[i];
    				if (d[y] > d[x] + cost[i]) {
    					d[y] = d[x] + cost[i];
    					if (!vis[y]) {
    						vis[y] = 1; 
    						q.push(y);
    					}
    				}
    			}
    	}
    	
    	return d[t] == inf ? 0 : d[t];
    }
    
    int main() {
    	memset(b1, 0, sizeof(b1));
    	memset(b2, 0, sizeof(b2));
    	memset(f1, 0, sizeof(f1));
    	memset(f2, 0, sizeof(f2));
    	scanf("%d%d", &n, &m);
    	for(int i = 1; i <= m; ++i) {
    		scanf("%d %s %s", &cost[i], a, b);
    		for(int j = 0; j < strlen(a); ++j)
    			if (a[j] == '+') b1[i] |= 1 << j;
    			else if (a[j] == '-') b2[i] |= 1 << j;
    		for(int j = 0; j < strlen(b); ++j)
    			if (b[j] == '+') f2[i] |= 1 << j;
    			else if (b[j] == '-') f1[i] |= 1 << j;
    	}
    	
    	printf("%d
    ", spfa((1 << n) - 1, 0));
    	
    	return 0;
    }
    

    13.星际转移问题 2016-04-18


      将每天转化为分层图,然后每天都跑最大流,若最大流大于等于k,则输出答案。特殊情况我还是面向数据编程,,,我怎么这么弱QAQ

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 2000003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    bool vis[N];
    queue <int> q;
    int point[N], cur[N], nxt[N], cap[N], d[N], to[N], S, T, cnt = 1;
    
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int flow = 0, f;
    	for(int &i = cur[u]; i; i = nxt[i])
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int flow = 0;
    	while (BFS()) {
    		for(int i = 0; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, inf);
    	}
    	return flow;
    }
    
    struct node {int r, num, a[103];} B[203];
    int n, m, k;
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    void mk(int &x) {x = (x == 0 ? n + 1 : (x == -1 ? n + 2 : x));}
    int main() {
    	read(n); read(m); read(k);
    	S = 0; T = N - 3;
    	for(int i = 1; i <= m; ++i) {
    		read(B[i].r); read(B[i].num);
    		for(int j = 1; j <= B[i].num; ++j)
    			read(B[i].a[j]), mk(B[i].a[j]);
    		B[i].a[0] = B[i].a[B[i].num];
    	}
    	int earth = n + 1, moon = n + 2, gh = moon, Q = 0;
    	
    	ins(S, earth, k), ins(earth, S, 0);
    	for(int Day = 1; Day <= 30; ++Day) {
    		for(int i = 1; i < gh; ++i) {
    			ins((Day - 1) * gh + i, Day * gh + i, inf);
    			ins(Day * gh + i, (Day - 1) * gh + i, 0);
    		}
    		ins(Day * gh + moon, T, inf), ins(T, Day * gh + moon, 0);
    		for(int i = 1; i <= m; ++i) {
    			int last = B[i].a[Day % B[i].num], now = B[i].a[(Day + 1) % B[i].num];
    			ins((Day - 1) * gh + last, Day * gh + now, B[i].r);
    			ins(Day * gh + now, (Day - 1) * gh + last, 0);
    		}
    		Q += Dinic();
    		if (Q >= k) {
    			printf("%d
    ", Day);
    			break;
    		}
    	}
    	
    	if (Q < k)
    		puts("0");
    	
    	return 0;
    }
    

    14.孤岛营救问题 2016-04-18


      在分层图上spfa,不是网络流,,,以后是不是遇到水的数据就应该考虑不同寻常的做法。

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 2000003;
    const int inf = 2139062143;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int cnt = 1, point[N], nxt[N], to[N], w[N], d[N];
    
    void spfa(int s) {
    	memset(vis, 0, sizeof(vis));
    	memset(d, 127, sizeof(d));
    	q.push(s); vis[s] = 1; d[s] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    }
    
    int n, m, p, k, S, map[16][16][16][16];
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; w[cnt] = z; point[x] = cnt;
    }
    int main() {
    	read(n); read(m); read(p); read(k);
    	memset(map, -1, sizeof(map));
    	int x1, x2, y1, y2, z, dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
    	for(int i = 1; i <= k; ++i) {
    		read(x1); read(y1); read(x2); read(y2); read(z);
    		map[x1][y1][x2][y2] = map[x2][y2][x1][y1] = z;
    	}
    	
    	read(S);
    	for(int i = 1; i <= S; ++i) {
    		read(x1); read(y1); read(z);
    		for(int j = 0; j < (1 << p); ++j)
    			if (((1 << (z - 1)) & j) == 0)
    				ins(j * n * m + (x1 - 1) * m + y1, (j | (1 << (z - 1))) * n * m + (x1 - 1) * m + y1, 0);
    	}
    	
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= m; ++j)
    			for(int nu = 0; nu < 4; ++nu) {
    				x1 = i + dx[nu]; y1 = j + dy[nu];
    				if (x1 > 0 && x1 <= n && y1 > 0 && y1 <= m) {
    					if (map[i][j][x1][y1] == -1) {
    						for(int l = 0; l < (1 << p); ++l)
    							ins(l * n * m + (i - 1) * m + j, l * m * n + (x1 - 1) * m + y1, 1);
    					} else if (map[i][j][x1][y1] > 0) {
    						for(int l = 0; l < (1 << p); ++l)
    							if ((1 << (map[i][j][x1][y1] - 1)) & l)
    								ins(l * n * m + (i - 1) * m + j, l * n * m + (x1 -1) * m + y1, 1);
    					}
    				}
    			}
    	
    	spfa(1);
    	int Q = inf;
    	for(int i = 0; i <= (1 << p); ++i)
    		Q = min(Q, d[i * n * m]);
    	printf("%d
    ", Q == inf ? -1 : Q);
    	
    	return 0;
    }
    

    15.汽车加油形式问题 2016-04-18


      还是最短路,,,BFS暴力过掉,不知道还有什么其他做法。

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    struct node {int x, y, gas, cos;};
    queue <node> q;
    int N, K, A, B, C, f[103][103][13], dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
    short a[103][103];
    
    int Q() {
    	node u, now;
    	memset(f, 127, sizeof(f));
    	f[1][1][K] = 0;
    	u.x = u.y = 1; u.gas = K; u.cos = 0;
    	q.push(u);
    	while (!q.empty()) {
    		u = q.front(); q.pop();
    		if (u.gas == 0) continue;
    		for(int i = 0; i < 4; ++i) {
    			now.x = u.x + dx[i]; now.y = u.y + dy[i];
    			if (now.x > 0 && now.x <= N && now.y > 0 && now.y <= N) {
    				now.gas = u.gas - 1; now.cos = u.cos;
    				if (now.x < u.x || now.y < u.y)
    					now.cos += B;
    				if (a[now.x][now.y]) {
    					now.gas = K; now.cos += A;
    					if (now.cos < f[now.x][now.y][now.gas])
    						f[now.x][now.y][now.gas] = now.cos, q.push(now);
    				} else {
    					if (now.cos < f[now.x][now.y][now.gas])
    						f[now.x][now.y][now.gas] = now.cos, q.push(now);
    					now.gas = K; now.cos += A + C;
    					if (now.cos < f[now.x][now.y][now.gas])
    						f[now.x][now.y][now.gas] = now.cos, q.push(now);
    				}
    			}
    		}
    	}
    	
    	int ret = 0x7fffffff;
    	for(int i = 0; i <= K; ++i)
    		ret = min(ret, f[N][N][i]);
    	return ret;
    }
    
    int main() {
    	read(N); read(K); read(A); read(B); read(C);
    	for(int i = 1; i <= N; ++i)
    		for(int j = 1; j <= N; ++j)
    			read(a[i][j]);
    	
    	printf("%d
    ", Q());
    	
    	return 0;
    }
    

    16.数字梯形问题 2016-04-18


      最小费用最大流,相当于写了3道水题,不过Ctrl+C,Ctrl+V大法好!建图时结点直接用坐标表示略偷懒

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], nxt[N], to[N], pre[N], from[N], cap[N], d[N], w[N], S, T, cnt = 1;
    
    bool spfa() {
    	for(int i = 0; i <= T; ++i) vis[i] = 0, d[i] = inf;
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[T] != inf;
    }
    int mcmf() {
    	int ret = 0, f, u;
    	while (spfa()) {
    		f = inf;
    		for(u = T; u != S; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = T; u != S; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += f * d[T];
    	}
    	return ret;
    }
    
    int m, n, ss, nn, x[103][103];
    void ins(int x, int y, int z, int zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    int main() {
    	read(m); read(n);
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= m + i - 1; ++j)
    			read(x[i][j]);
    	
    	nn = (m + n) * n; T = 2 * nn + 2; ss = T - 1; S = 0;
    	ins(S, ss, m, 0); ins(ss, S, 0, 0);
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= m + i - 1; ++j) {
    			ins((i - 1) * (n + m) + j, (i - 1) * (n + m) + j + nn, 1, - x[i][j]);
    			ins((i - 1) * (n + m) + j + nn, (i - 1) * (n + m) + j, 0, x[i][j]);
    			if (i == n) {
    				ins((i - 1) * (n + m) + j + nn, T, 1, 0);
    				ins(T, (i - 1) * (n + m) + j + nn, 0, 0);
    			} else {
    				if (i == 1) {
    					ins(ss, (i - 1) * (n + m) + j, 1, 0);
    					ins((i - 1) * (n + m) + j, ss, 0, 0);
    				}
    				ins((i - 1) * (n + m) + j + nn, i * (n + m) + j, 1, 0);
    				ins(i * (n + m) + j, (i - 1) * (n + m) + j + nn, 0, 0);
    				ins((i - 1) * (n + m) + j + nn, i * (n + m) + j + 1, 1, 0);
    				ins(i * (n + m) + j + 1, (i - 1) * (n + m) + j + nn, 0, 0);
    			}
    		}
    	int Q = mcmf();
    	printf("%d
    ", - Q);
    	
    	memset(point, 0, sizeof(point));
    	ins(S, ss, m, 0); ins(ss, S, 0, 0);
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= m + i - 1; ++j) {
    			ins((i - 1) * (n + m) + j, (i - 1) * (n + m) + j + nn, inf, - x[i][j]);
    			ins((i - 1) * (n + m) + j + nn, (i - 1) * (n + m) + j, 0, x[i][j]);
    			if (i == n) {
    				ins((i - 1) * (n + m) + j + nn, T, inf, 0);
    				ins(T, (i - 1) * (n + m) + j + nn, 0, 0);
    			} else {
    				if (i == 1) {
    					ins(ss, (i - 1) * (n + m) + j, 1, 0);
    					ins((i - 1) * (n + m) + j, ss, 0, 0);
    				}
    				ins((i - 1) * (n + m) + j + nn, i * (n + m) + j, 1, 0);
    				ins(i * (n + m) + j, (i - 1) * (n + m) + j + nn, 0, 0);
    				ins((i - 1) * (n + m) + j + nn, i * (n + m) + j + 1, 1, 0);
    				ins(i * (n + m) + j + 1, (i - 1) * (n + m) + j + nn, 0, 0);
    			}
    		}
    	Q = mcmf();
    	printf("%d
    ", - Q);
    	
    	memset(point, 0, sizeof(point));
    	ins(S, ss, m, 0); ins(ss, S, 0, 0);
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= m + i - 1; ++j) {
    			ins((i - 1) * (n + m) + j, (i - 1) * (n + m) + j + nn, inf, - x[i][j]);
    			ins((i - 1) * (n + m) + j + nn, (i - 1) * (n + m) + j, 0, x[i][j]);
    			if (i == n) {
    				ins((i - 1) * (n + m) + j + nn, T, inf, 0);
    				ins(T, (i - 1) * (n + m) + j + nn, 0, 0);
    			} else {
    				if (i == 1) {
    					ins(ss, (i - 1) * (n + m) + j, 1, 0);
    					ins((i - 1) * (n + m) + j, ss, 0, 0);
    				}
    				ins((i - 1) * (n + m) + j + nn, i * (n + m) + j, inf, 0);
    				ins(i * (n + m) + j, (i - 1) * (n + m) + j + nn, 0, 0);
    				ins((i - 1) * (n + m) + j + nn, i * (n + m) + j + 1, inf, 0);
    				ins(i * (n + m) + j + 1, (i - 1) * (n + m) + j + nn, 0, 0);
    			}
    		}
    	Q = mcmf();
    	printf("%d
    ", - Q);
    	
    	return 0;
    }
    

    17.运输问题 2016-04-19


      最小费用最大流,,,

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], nxt[N], cap[N], from[N], w[N], to[N], d[N], pre[N], S, T, cnt = 1;
    
    bool spfa() {
    	for(int i = 1; i <= T; ++i) vis[i] = 0, d[i] = inf;
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[T] != inf;
    }
    int mcmf() {
    	int ret = 0, f, u;
    	while (spfa()) {
    		f = inf;
    		for(u = T; u != S; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = T; u != S; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += f * d[T];
    	}
    	return ret;
    }
    
    int m, n, x[503], c[503][503];
    void ins(int x, int y, int z, int zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    int main() {
    	read(m); read(n);
    	S = 0; T = m + n + 1;
    	for(int i = 1; i <= m; ++i)
    		read(x[i]), ins(S, i, x[i], 0), ins(i, S, 0, 0);
    	for(int i = m + 1; i < T; ++i)
    		read(x[i]), ins(i, T, x[i], 0), ins(T, i, 0, 0);
    	for(int i = 1; i <= m; ++i)
    		for(int j = m + 1; j < T; ++j) {
    			read(c[i][j]);
    			ins(i, j, inf, c[i][j]);
    			ins(j, i, 0, - c[i][j]);
    		}
    	int Q = mcmf();
    	printf("%d
    ", Q);
    	
    	memset(point, 0, sizeof(point)); cnt = 1;
    	for(int i = 1; i <= m; ++i)
    		ins(S, i, x[i], 0), ins(i, S, 0, 0);
    	for(int i = m + 1; i < T; ++i)
    		ins(i, T, x[i], 0), ins(T, i, 0, 0);
    	for(int i = 1; i <= m; ++i)
    		for(int j = m + 1; j < T; ++j) {
    			ins(i, j, inf, - c[i][j]);
    			ins(j, i, 0, c[i][j]);
    		}
    	Q = - mcmf();
    	printf("%d
    ", Q);
    	
    	return 0;
    }
    

    18.分配问题 2016-04-19


      最小费用最大流,,,,,,,,,,,,,,,,,

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], nxt[N], cap[N], from[N], w[N], to[N], d[N], pre[N], S, T, cnt = 1;
    
    bool spfa() {
    	for(int i = 1; i <= T; ++i) vis[i] = 0, d[i] = inf;
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[T] != inf;
    }
    int mcmf() {
    	int ret = 0, f, u;
    	while (spfa()) {
    		f = inf;
    		for(u = T; u != S; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = T; u != S; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += f * d[T];
    	}
    	return ret;
    }
    
    int n, c[503][503];
    void ins(int x, int y, int z, int zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    int main() {
    	read(n);
    	S = 0; T = n + n + 1;
    	for(int i = 1; i <= n; ++i)
    		ins(S, i, 1, 0), ins(i, S, 0, 0);
    	for(int i = n + 1; i < T; ++i)
    		ins(i, T, 1, 0), ins(T, i, 0, 0);
    	for(int i = 1; i <= n; ++i)
    		for(int j = n + 1; j < T; ++j) {
    			read(c[i][j]);
    			ins(i, j, inf, c[i][j]);
    			ins(j, i, 0, - c[i][j]);
    		}
    	int Q = mcmf();
    	printf("%d
    ", Q);
    	
    	memset(point, 0, sizeof(point)); cnt = 1;
    	for(int i = 1; i <= n; ++i)
    		ins(S, i, 1, 0), ins(i, S, 0, 0);
    	for(int i = n + 1; i < T; ++i)
    		ins(i, T, 1, 0), ins(T, i, 0, 0);
    	for(int i = 1; i <= n; ++i)
    		for(int j = n + 1; j < T; ++j) {
    			ins(i, j, inf, - c[i][j]);
    			ins(j, i, 0, c[i][j]);
    		}
    	Q = - mcmf();
    	printf("%d
    ", Q);
    	
    	return 0;
    }
    

    19.负载平衡问题 2016-04-19


      还是最小费用最大流,我第一次WA了,因为只是将$X_i$连了一条向$Y_i$的流量无穷大的边,但有可能出现一些货物运输跨过几个仓库的情况,于是便从$Y_i$向$X_i$连一流量无穷大的边,保证货物在运输一次之后可以继续运输。

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 10003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], nxt[N], from[N], to[N], pre[N], cap[N], w[N], d[N], S, T, cnt = 1;
    
    bool spfa() {
    	for(int i = 1; i <= T; ++i) vis[i] = 0, d[i] = inf;
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[T] != inf;
    }
    int mcmf() {
    	int ret = 0, f, u;
    	while (spfa()) {
    		f = inf;
    		for(u = T; u != S; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = T; u != S; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += f * d[T];
    	}
    	return ret;
    }
    
    int n, x, Qsum = 0, to1, to2;
    void ins(int x, int y, int z, int zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    int main() {
    	read(n);
    	S = 0; T = (n << 1) + 1;
    	for(int i = 1; i <= n; ++i)
    		read(x), ins(S, i, x, 0), ins(i, S, 0, 0), Qsum += x;
    	for(int i = n + 1; i < T; ++i)
    		ins(i, T, Qsum / n, 0), ins(T, i, 0, 0);
    	for(int i = 1; i <= n; ++i) {
    		ins(i, i + n, inf / 2, 0);
    		ins(i + n, i, inf / 2, 0);
    		to1 = i == 1 ? n + n : i - 1 + n;
    		to2 = i == n ? 1 + n : i + 1 + n;
    		ins(i, to1, inf, 1);
    		ins(to1, i, 0, -1);
    		ins(i, to2, inf, 1);
    		ins(to2, i, 0, -1);
    	}
    	
    	int Q = mcmf();
    	printf("%d
    ", Q);
    	
    	return 0;
    }
    

    20.深海机器人问题 2016-04-19


      BYVoid的题解上说是线性规划网络优化,可是我并没有看出来线性规划用在哪里了,,,这道题建图时因为一条道路上的生物只能采集一次,所以得设流量限制为1,但因为在这条路上采集后其他机器人还可以再走,所以再连一条容量为无穷,费用为0的边,保证了后来的任何机器人都可以从这条路上走过而且不会计算费用233。

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], from[N], nxt[N], to[N], cap[N], d[N], pre[N], w[N], S, T, cnt = 1;
    
    bool spfa() {
    	for(int i = 0; i <= T; ++i) vis[i] = 0, d[i] = inf;
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[T] != inf;
    }
    int mcmf() {
    	int ret = 0, f, u;
    	while (spfa()) {
    		f = inf;
    		for(u = T; u != S; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = T; u != S; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += d[T] * f;
    	}
    	return ret;
    }
    
    int P, Q, a, b, r, x, y;
    void ins(int x, int y, int z, int zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    int main() {
    	read(a); read(b); read(P); read(Q);
    	S = (P + 1) * (Q + 1) + 1; T = S + 1;
    	for(int i = 0; i <= P; ++i)
    		for(int j = 0; j < Q; ++j) {
    			read(x);
    			ins(i * (Q + 1) + j, i * (Q + 1) + j + 1, 1, - x);
    			ins(i * (Q + 1) + j + 1, i * (Q + 1) + j, 0, x);
    			ins(i * (Q + 1) + j, i * (Q + 1) + j + 1, inf, 0);
    			ins(i * (Q + 1) + j + 1, i * (Q + 1) + j, 0, 0);
    		}
    	for(int j = 0; j <= Q; ++j)
    		for(int i = 0; i < P; ++i) {
    			read(x);
    			ins(i * (Q + 1) + j, (i + 1) * (Q + 1) + j, 1, - x);
    			ins((i + 1) * (Q + 1) + j, i * (Q + 1) + j, 0, x);
    			ins(i * (Q + 1) + j, (i + 1) * (Q + 1) + j, inf, 0);
    			ins((i + 1) * (Q + 1) + j, i * (Q + 1) + j, 0, 0);
    		}
    	for(int i = 1; i <= a; ++i) {
    		read(r); read(x); read(y);
    		ins(S, x * (Q + 1) + y, r, 0);
    		ins(x * (Q + 1) + y, S, 0, 0);
    	}
    	for(int i = 1; i <= b; ++i) {
    		read(r); read(x); read(y);
    		ins(x * (Q + 1) + y, T, r, 0);
    		ins(T, x * (Q + 1) + y, 0, 0);
    	}
    	
    	int QQ = - mcmf();
    	printf("%d
    ", QQ);
    	
    	return 0;
    }
    

    21.最长k可重区间集问题 2016-04-19


      查了3h错,因为离散化完全写错了,还有这道题数据辣么水,为什么要写离散化(┙>∧<)┙へ┻┻。重写了离散化之后还是WA三个点,又查了1h+后在codevs的题解上发现数据错了(゚皿゚メ)

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 100003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], from[N], nxt[N], to[N], cap[N], w[N], d[N], pre[N], S, T, cnt = 1;
    
    bool spfa() {
    	for(int i = 1; i <= T; ++i) vis[i] = 0, d[i] = inf;
    	q.push(S); vis[S] = 0; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for(int i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[T] != inf;
    }
    int mcmf() {
    	int ret = 0, f, u;
    	while (spfa()) {
    		f = inf;
    		for(u = T; u != S; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = T; u != S; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += f * d[T];
    	}
    	return ret;
    }
    
    struct node {
    	int l, r;
    } a[1003];
    int n, k, H[2003], id[2003], HH[2003], num = 1, cos, He[2003];
    bool cmp2(int X, int Y) {return H[X] < H[Y];}
    void ins(int x, int y, int z, int zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    int main() {
    	read(n); read(k);
    	for(int i = 1; i <= n; ++i)
    		read(H[(i << 1) - 1]), read(H[i << 1]);
    	for(int i = 1; i <= (n << 1); ++i)
    		id[i] = i;
    	sort(id + 1, id + (n << 1) + 1, cmp2);
    	for(int i = 1; i <= (n << 1); ++i) {
    		He[num] = H[id[i]];
    		HH[id[i]] = num;
    		if (H[id[i]] != H[id[i + 1]] && i != (n << 1)) ++num;
    	}
    	
    	S = 0; T = num + 1;
    	ins(S, 1, k, 0); ins(1, S, 0, 0);
    	ins(num, T, k, 0); ins(T, num, 0, 0);
    	for(int i = 1; i < num; ++i)
    		ins(i, i + 1, inf, 0), ins(i + 1, i, 0, 0);
    	for(int i = 1; i < (n << 1); i += 2) {
    		cos = He[HH[i + 1]] - He[HH[i]];
    		ins(HH[i], HH[i + 1], 1, - cos);
    		ins(HH[i + 1], H[i], 0, cos);
    		printf("%d %d : %d
    ", HH[i], HH[i + 1], cos);
    	}
    	
    	int Q = - mcmf();
    	printf("%d
    ", Q);
    	
    	return 0;
    }
    

    22.最长k可重线段集问题 2016-04-19


      查错查了一个下午,发现各大OJ上此题AC率都是0,最后Menci神犇说数据有误,,,不管对不对,我还是先把自己愚蠢的代码贴上来吧

    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const long long N = 1000003;
    const long long inf = 0x7fffffff;
    long long getint() {
    	long long k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <long long> q;
    bool vis[N];
    long long point[N], from[N], nxt[N], to[N], cap[N], d[N], w[N], pre[N], S, T, cnt = 1;
    
    bool spfa() {
    	for(long long i = 0; i <= T; ++i) vis[i] = 0, d[i] = inf;
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		long long u = q.front(); q.pop(); vis[u] = 0;
    		for(long long i = point[u]; i; i = nxt[i])
    			if (cap[i] && d[to[i]] > d[u] + w[i]) {
    				d[to[i]] = d[u] + w[i];
    				pre[to[i]] = i;
    				if (!vis[to[i]]) {
    					vis[to[i]] = 1;
    					q.push(to[i]);
    				}
    			}
    	}
    	return d[T] != inf;
    }
    long long mcmf() {
    	long long ret = 0, f, u;
    	while (spfa()) {
    		f = inf;
    		for(u = T; u != S; u = from[pre[u]]) f = min(f, cap[pre[u]]);
    		for(u = T; u != S; u = from[pre[u]]) cap[pre[u]] -= f, cap[pre[u] ^ 1] += f;
    		ret += d[T] * f;
    	}
    	return ret;
    }
    
    long long n, k, num = 1, W[1003], H[2003], id[2003], HH[2003];
    void ins(long long x, long long y, long long z, long long zz) {
    	nxt[++cnt] = point[x]; from[cnt] = x; to[cnt] = y; cap[cnt] = z; w[cnt] = zz; point[x] = cnt;
    }
    long long sqr(long long x) {return x * x;}
    bool cmp(long long X, long long Y) {return H[X] < H[Y];}
    int main() {
    	long long x1, x2, y1, y2;
    	read(n); read(k);
    	for(long long i = 1; i <= n; ++i) {
    		read(x1); read(y1); read(x2); read(y2);
    		if (x1 > x2) swap(x1, x2), swap(y1, y2);
    		H[(i << 1) - 1] = x1; H[i << 1] = x2;
    		W[i] = floor(sqrt(sqr(x1 - x2) + sqr(y1 - y2)));
    	}
    	for(long long i = 1; i <= (n << 1); ++i)
    		id[i] = i;
    	sort(id + 1, id + (n << 1) + 1, cmp);
    	for(long long i = 1; i <= (n << 1); ++i) {
    		HH[id[i]] = num;
    		if (H[id[i]] != H[id[i + 1]] && i != (n << 1)) ++num;
    	}
    	S = 0; T = (num << 1) + 1;
    	ins(S, 1, k, 0); ins(1, S, 0, 0);
    	ins(num << 1, T, k, 0); ins(T, num << 1, 0, 0);
    	for(long long i = 1; i < (num << 1); ++i)
    		ins(i, i + 1, inf, 0), ins(i + 1, i, 0, 0);
    	for(long long i = 1; i <= n; ++i) {
    		long long le = HH[(i << 1) - 1], ri = HH[i << 1];
    		if (le == ri) {
    			ins((le << 1) - 1, le << 1, 1, - W[i]);
    			ins(le << 1, (le << 1) - 1, 0, W[i]);
    		} else {
    			ins(le << 1, (ri << 1) - 1, 1, - W[i]);
    			ins((ri << 1) - 1, le << 1, 0, W[i]);	
    		}
    	}
    	
    	long long Q = - mcmf();
    	printf("%d
    ", Q);
    	
    	return 0;
    }
    

    23.火星探险问题 2016-04-19


      数据还是有问题!!!和深海机器人问题差不多,我就不做了吧,,,毕竟A不了

    24.骑士共存问题 2016-04-19


      典型最大权闭合图,染色后建图,,,zyf神犇说这是道水题←此话没有特别意思

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define read(x) x=getint()
    using namespace std;
    const int N = 1000003;
    const int inf = 0x7fffffff;
    int getint() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - '0';
    	return k * fh;
    }
    
    queue <int> q;
    bool vis[N];
    int point[N], cur[N], d[N], cap[N], nxt[N], to[N], S, T, cnt = 1;
    
    bool BFS() {
    	memset(vis, 0, sizeof(vis));
    	q.push(S); vis[S] = 1; d[S] = 0;
    	while (!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = point[u]; i; i = nxt[i])
    			if (!vis[to[i]] && cap[i]) {
    				d[to[i]] = d[u] + 1;
    				vis[to[i]] = 1;
    				q.push(to[i]);
    			}
    	}
    	return vis[T];
    }
    int DFS(int u, int a) {
    	if (u == T || !a) return a;
    	int flow = 0, f;
    	for(int &i = cur[u]; i; i = nxt[i])	
    		if (d[to[i]] == d[u] + 1 && (f = DFS(to[i], min(a, cap[i]))) > 0) {
    			flow += f; a -= f; cap[i] -= f; cap[i ^ 1] += f;
    			if (!a) break;
    		}
    	return flow;
    }
    int Dinic() {
    	int flow = 0, i;
    	while (BFS()) {
    		for(i = 0; i <= T; ++i) cur[i] = point[i];
    		flow += DFS(S, inf);
    	}
    	return flow;
    }
    
    bool pd[203][203];
    int dx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}, dy[8] = {2, 1, -1, -2, -2, -1, 1, 2};
    int n, m, x, y;
    void ins(int x, int y, int z) {
    	nxt[++cnt] = point[x]; to[cnt] = y; cap[cnt] = z; point[x] = cnt;
    }
    int main() {
    	read(n); read(m);
    	for(int i = 1; i <= m; ++i) {
    		read(x); read(y);
    		pd[x][y] = 1;
    	}
    	S = 0; T = n * n + 1;
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= n; ++j)
    			if (!pd[i][j])
    				if ((i + j) % 2 ==0) {
    					ins(S, (i - 1) * n + j, 1);
    					ins((i - 1) * n + j, S, 0);
    				} else {
    					ins((i - 1) * n + j, T, 1);
    					ins(T, (i - 1) * n + j, 0);
    				}
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= n; ++j)
    			if (!pd[i][j] && (i + j) % 2 == 0)
    				for(int k = 0; k < 8; ++k) {
    					x = i + dx[k]; y = j + dy[k];
    					if (x < 1 || x > n || y < 1 || y > n || pd[x][y])
    						continue;
    					int now = (x - 1) * n + y;
    					ins((i - 1) * n + j, now, inf);
    					ins(now, (i - 1) * n + j, 0);
    				}
    	
    	int Q = Dinic();
    	printf("%d
    ", n * n - m - Q);
    	
    	return 0;
    }
    

    2016-04-19:线性规划与网络流24题就告一段落了,因为8机器人路径规划问题有点困难,暂时先放一放,还有最长k可重线段集问题和火星探险问题2道题的测试数据存在较大问题,没有办法AC,所以那三道题就先被我抛弃了QAQ。说好的线性规划呢?做完了连线性规划的影子都没见到,还是我太弱根本不懂线性规划QuQ。今天是停课第二天,我有没有取得进步自己也说不清楚,走一步看一步吧。CTSC2016, SDOI2016 Round2 Bless All!

  • 相关阅读:
    《入门经典》——8.4
    《A First Course in Probability》-chaper7-期望的性质-期望的性质-协方差
    计算几何讲义——计算几何中的欧拉定理
    Gym
    hdu6053
    ACdream1032(树形DP)
    hdu6040
    hdu6035(树形DP)
    hdu6038
    Codeforces #425 Div2 D
  • 原文地址:https://www.cnblogs.com/abclzr/p/5380247.html
Copyright © 2020-2023  润新知