北京大学ACM暑期课讲义-网络流

合集下载

北京大学ACM暑期课讲义-计算几何教程共158页

北京大学ACM暑期课讲义-计算几何教程共158页

北京大学ACM暑期课讲义计算几何教程
26、机遇对于有准备的头脑有特别的 亲和力 。 27、自信是人格的核心。
28、目标的坚定是性格中最必要的力 量泉源 之一, 也是成 功的利 器之一 。没有 它,天 才也会 在矛盾 无定的 迷径中 ,徒劳 无功。- -查士 德斐尔 爵士。 29、困难就是机遇。--温斯顿.丘吉 尔。 30、我奋斗,所以我快乐。--格林斯 潘。
46、我们若已接受最坏的,就再没有什么损失。——卡耐基 47、书到用时方恨少、事非经过不知难。——陆游 48、书籍把我们引入最美好的社会,使我们认识各个时代的伟大智者。——史美尔斯 49、熟读唐诗三百扎特

北京大学ACM暑期课讲义-计算几何教程

北京大学ACM暑期课讲义-计算几何教程
Computational Geometry
计算几何教程
计算几何的恶心之处
代码长,难写。
需要讨论各种边界情况。后面所介绍的算
法,有些对于边界情况的处理很完美,不 需要再做讨论;有些则不然,需要自行处 理边界情况。
精度误差

二维矢量
2-Dimension Vector
矢量
既有大小又有方向的量。
算法演示
2 被弹出栈,3 进栈。
算法演示
没有点被弹出栈,4 进栈。
算法演示
4 被弹出栈,5 进栈。
算法演示
5 被弹出栈,6 进栈。
算法演示
6 被弹出栈,7 进栈。
算法演示
如此直到下凸壳被找到。
算法演示
倒序进行扫描找到上凸壳。
Graham 扫描的时间复杂度
这太傻缺了。算法的瓶颈在排序,所以时
总时间复杂度 O(N2 log N)。
算法扩展
SPOJ CIRUT
求恰好被覆盖 1 次、2 次、„、N 次的面积。
算法的本质在于对“裸露”部分进行处理。
这种方法也可以用于求很多圆与很多凸多 边形的面积并——但是情况复杂得多,要 讨论的情况也多得多。
三维矢量
3-Dimension Vector
总体来说讨论比较辛苦,写起来不算很难。
精度存在比较大的问题,而且半平面交的
题目一般都容许 O(N2) 算法,所以并不是 很常用。
半平面交练习题
POJ 1279 POJ 3525 POJ 2451 POJ 3384
求多边形的核。核中的点满足其到多边形边 界上任一点之间的线段只与多边形在那一点相交。 求凸多边形最大内切圆半径。 裸的半平面交。朱泽园专门为他的算法出的 题,要求 O(N log N) 算法。 求在凸多边形内部放两个半径为 r 的圆所能 覆盖的最大面积。两圆可以重叠,但不能与多边形相交。 需要用到旋转卡壳。

北京大学ACM国际大学生程序设计竞赛课件4

北京大学ACM国际大学生程序设计竞赛课件4

1048
输入:
Follow My Logic
输入数据包含多个输入数据块.每个输入数据块包含以 下部分:
一个电路图,以上述形式表示,用只含'*'的单独一行结束. 多行01字符串,每行对应一组数据,包含26个0或1,分别对应AZ的值.用只含'*'的单独一行结束
输出:
对每组输入数据,输出对应的电路输出值. 每个结果占一行. 不同输入数据块的输出结果之间用空行隔开.
问题求解与程序设计 第三讲 模拟问题李Βιβλιοθήκη 新 2004.2 – 2004.6
内容提要
作业总结 - 1016 作业总结 - 1048 讨论 – 1207 作业 – 1207
1016 Numbers That Count
题意 count the numbers of each digit to form the new number 123321 -〉212223 1)Self-inventory 2) enter self inventory after k steps 3) enter inventory loop of length k 4) can not determined after 15 steps
Can not be classified
源程序
1016 c0400348274.txt 1016 c0400348198.txt
1048
Follow My Logic
对于一个逻辑电路和给定的输入值,计算该电路 对于一个逻辑电路和给定的输入值, 的输出值.该逻辑电路有一个或多个输入端, 的输出值.该逻辑电路有一个或多个输入端, 零 个或多个逻辑门电路,和一个输出端. 个或多个逻辑门电路,和一个输出端.本题中用 标准ASCll字符来表示逻辑电路:横竖导线分别 字符来表示逻辑电路: 标准 字符来表示逻辑电路 表示, 表示, 用'-'和'|'表示,转折点用'+'表示,输入端用 和 表示 转折点用' 表示 大写字母' 表示, 表示, 大写字母'A'-'Z'表示,输出端用问号'?'表示, 表示 输出端用问号' 表示 小写字母' 表示取反 与门, 表示取反. 小写字母'o'表示取反.与门,或门及电路各部 分示例如下: 分示例如下:

北大ACM训练课程点

北大ACM训练课程点

ACM/ICPC竞赛中用到的大量算法,包括:组合数学、数论、图论、计算几何、高级数据结构等。

北京大学
课程内容共八个专题,除理论知识外还包括精选例题讲解:
7.14 数据结构(一): 线段树,树状数组,二维线段树
7.15 数学题:组合数学,数论等
7.16 数据结构(二): 并查集, DFA, Trie图等
7.17 若干图论问题:最小生成树最短路强连通分量、桥和割点等
7.21 计算几何:线与线求交,线与面求交,求凸包,半平面求交等
7.22 搜索:深搜,广搜,剪枝,A*算法
7.24 动态规划
7.24 网络流算法:基本的网络流算法,Dinic算法,带上下界的网络流,最小费用
流。

ACM暑期培训资料(ppt28张)

ACM暑期培训资料(ppt28张)

大整数除法
1、链接地址
/problem?id=2737
2、问题描述
– 求两个大的正整数相除的商
输入数据
第1 行是测试数据的组数n,每组测试数据占2 行,第1 行是被除数,第2 行是除数。每组测试数据之间有一个空 行,每行数据不超过100 个字符
输出要求
n 行,每组测试数据有一行输出是相应的整数商
规律:一个数的第i 位和另一个数的第j 位相乘所得的数,一 定是要累加到结果的第i+j 位上。这里i, j 都是从右往左,从 0 开始数。
POJ2389 参考程序
#include<iostream> #include<string> using namespace std; const int MAXLEN=200+10; int a[MAXLEN],b[MAXLEN]; int c[2*MAXLEN]; string st1,st2; int i,j,k; //字符串s转换为整型数组t void tran(string s,int *t) { int m,l; l=s.length(); for(m=0;m<l;m++) t[m]=s[l-1-m]-'0'; }

//下面判断p1 是否比p2 大,如果不是,返回-1 if( nLen1 == nLen2 ) { for( i = nLen1-1; i >= 0; i -- ) { if( p1[i] > p2[i] ) break; //p1>p2 else if( p1[i] < p2[i] ) return -1; //p1<p2 } } for( i = 0; i < nLen1; i ++ ) { //要求调用本函数确保当i>=nLen2 时,p2[i] = 0 p1[i] -= p2[i]; if( p1[i] < 0 ) { p1[i]+=10; p1[i+1] --; } } for( i = nLen1 -1 ; i >= 0 ; i-- ) if( p1[i] )//找到最高位第一个不为0 return i + 1; return 0;//全部为0,说明两者相等 }

ACM暑期培训课程图论.ppt

ACM暑期培训课程图论.ppt

E问题
OUTPUT FORMAT
输出应当有F+1行,每行一个整数,依次表示路径经 过的顶点号。注意数据可能有多组解,但是只有上面题目 要求的那一组解是认为正确的。
SAMPLE OUTPUT(fence.out) 1 2 3 4 2 5 4 6 5 7
E问题
很显然,这是一个欧拉路径问题,我们要做的就是读入栅栏的 构图后,找到图中的一条欧拉路径。
图的连通性
4. 有向图的强连通分支
在下面的几页中,我们可以看到求图的 强连通分支的实例。
首先,图(a)为有向图G,其中的阴影部 分是G的强连通分支,在对图G进行DFS 的过程中,我们对每个顶点都标出了其 开始搜索时刻preOrder与完成时刻 postOrder,黑色边为DFS搜索树树枝;
可以看到,图G共有 4个强连通分支:
{a,b,e}
{c,d}
{f,g}
{h}
图的连通性
4. 有向图的强连通分量
(b)图中G的转置图G*。图中说明了求 强连通分支算法第3部计算出的深度优 先树,其中黑色边是树枝。每个强连通
子图对应于一棵深度优先树。图中黑色 顶点b,c,g和h是强连通子图中每个顶点 的祖先,这些顶点也是对G*进行深度 优先搜索所产生的深度优先树的树根。
int map[MAXV][MAXV]; //map[i][j]记录顶点i和顶点j之 间的路径数目
int deg[MAXV]; int path[MAXE]; 径
//deg[i]记录顶点i的度数 //path数组用来存放找到的欧拉路
int fn,minv,maxv,pathnum=0; //minv为顶点最小编号,maxv为顶点最大编号
G有欧拉回路(G为欧拉图):G连通,G中均为偶度顶点。

图论讲义第9章-网络流理论

图论讲义第9章-网络流理论

注:网络 N 的一个割 K 称为最小割,如果网络 N 中不存在割 K′使得 CapK ′ < CapK 。 推论 9.1.1 设 f * 是网络 N 的一个最大流,K*是 N 的一个最小割,则 Val f * ≤ CapK * . 证明显然。 推论 9.1.2 设 f 是 N 的一个可行流,K 是 N 的一个割,若 Val f = CapK ,则 f 是最大流而
a∈K

(S ) =
a∈( S , S )

f (a ) ≥ 0 。
由引理 9.1.1, Val f = f + ( S ) − f − ( S ) ≤ CapK , 可见第 一个结论成立。另外注意到 f + ( S ) = CapK 当且仅当
S K
S
( S , S ) 中每条弧都是 f 饱和的;而 f − ( S ) = 0 当且仅当 ( S , S ) 中每条弧都是 f 零的,故定理的第二个结论也成立。证毕。
v2 v1 x P Q v3 y v6 v4 v5
定义 9.2.2 设 f 是网络 N = (V , x, y , A, C ) 中的一可行流,P 是 N 中一条 x-y 路。如果对于 P 上任一条弧
a ,都有
(1) 若弧 a 是 P 的正向弧,则 Δf ( a ) (2) 若弧 a 是 P 的反向弧,则 Δf ( a )
Байду номын сангаас
§9.1 网络与网络流的基本概念
定义 9.1.1 一个网络 N=(V,A)是指一个连通无环弧且满足下列条件的有向图: (1) 有一个顶点子集 X,其每个顶点的入度都为 0; (2) 有一个与 X 不相交的顶点子集 Y,其每个顶点的出度都为 0; (3) 每条弧都有一个非负的权,称为弧的容量。 注: 上述网络 N 可写作 N=(V, X, Y, A, C),X 称为网络的发点集或源点集,Y 称为网络的 收点集或汇点集,C 称为网络的容量函数。 例:

北京大学ACM暑期课讲义-lcc-博弈

北京大学ACM暑期课讲义-lcc-博弈
– 如果当前是我的回合,无论怎么做,轮到对方时, 对方都存在一种必胜策略,那么当前我面对的局面 就是必败局面
• 例:取石子问题
– 有一堆n个石子 两人轮流取 每次可以取1..m个 没得取的判负 在游戏中,n不断变化,m是定值 一个局面可以用当前的石子数n来表示 n = 0 必败 n = 1..m都是必胜局面 n = m+1 是必败局面(为什么?) n = m+2.. 2m+1 是必胜局面(为什么?)
– 附加问题:先手必胜时,输出当前一步可选 步
• 最终局面都是P局面 • 对于一个局面,若至少有一种操作使它变为P局 面,则它是N局面
– 如果当前是我的回合,我有一种操作选择,使得下 回合对方面对的局面是个必输局面,那么我的局面 就是必胜局面 – 问题:如何寻找这一步操作选择?(输出解)
• 对于一个局面,无论如何操作都使它变为N局面, 则它是P局面
• 双方每步可以从并行存在的多个子游戏中选择 一个操作
– 维度可以进一步变得更多 – 可能存在一个子游戏,由同一个玩家连续两次对其 操作
• 对sg函数来说:怎么变都无所谓,它只关心所 有子局面的异或值
– Sg(x)的变量x永远是一维的。
竞赛中的博弈题策略
• 利用最简单的N-P图染色来判定 • 博弈搜索:用搜索方式来对图染色
• 同样可以用拓扑序对节点计算sg值
SG函数与NP局面的关系
• 初始节点(必须是P节点)没有出边, sg = 0 • 若v有边指向某sg(vi) = 0的vi,则sg(v)>0 • 若v没有边指向某sg(vi) = 0的vi,则sg(v) =0
• 所有P节点sg = 0 • 所有N节点sg > 0
– 可以看做α-β剪枝的特例

acm知识点

acm知识点
转一个搞ACM需要的掌握的算法.
要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来.
适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什么就眼红,
发挥自己的长处,这才是重要的.
第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,
STL中的数据结构
vector
deque
set / map
动态规划 / 记忆化搜索
动态规划和记忆化搜索在思考方式上的区别
最长子序列系列问题
最长不下降子序列
最长公共子序列
最长公共不下降子序列
快速数论变换
……
素数问题
概率判素算法
概率因子分解
数据结构
组织结构
二叉堆
左偏树
二项树
胜者树
跳跃表
样式图标
弦图的性质和判定
组合数学
解决组合数学问题时常用的思想
逼近
递推 / 动态规划
概率问题
Polya定理
计算几何 / 解析几何
计算几何的核心:叉积 / 面积
解析几何的主力:复数
基本形
因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打
出来.
1.最短路(Floyd、Dijstra,BellmanFord)
2.最小生成树(先写个prim,kruscal要用并查集,不好写)
3.大数(高精度)加减乘除
4.二分查找. (代码可在五行以内)
5.叉乘、判线段相交、然后写个凸包.
(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)

acm-icpc暑期课_最短路

acm-icpc暑期课_最短路

acm-icpc暑期课_最短路北京⼤学暑期课《ACM/ICPC 竞赛训练》最短路算法本讲义为四处抄袭后改编⽽成,来源已不可考。

仅⽤于内部授课北京⼤学信息学院郭炜 guo_wei@/doc/d83c4f84bb68a98270fefa4a.html/doc/d83c4f84bb68a98270fefa4a.html /guoweiofpkuDijkstra 算法●解决⽆负权边的带权有向图或⽆向图的单源最短路问题●贪⼼思想,若离源点s 前k-1近的点已经被确定,构成点集P ,那么从s 到离s 第k 近的点t 的最短路径,{s,p 1,p 2…p i ,t}满⾜s,p 1,p 2…p i ∈P 。

●否则假设pi ?P ,则因为边权⾮负,pi 到t 的路径≥0,则d[pi]≤d[t],pi 才是第k 近。

将pi 看作t ,重复上⾯过程,最终⼀定会有找不到pi 的情况●d[i]=min(d[p i ]+cost(p i ,i)),i ?P,p i ∈P d[t]=min(d[i]) ,i ?P基本思想●初始令d[s]=0,d[i]=+∞,P=?●找到点i?P,且d[i]最⼩●把i添⼊P,对于任意j?P,若d[i]+cost(i,j)d[j]=d[i]+cost(i,j)。

●⽤邻接表,不优化,时间复杂度O(V2+E)●Dijkstra+堆的时间复杂度 o(ElgV)●⽤斐波那契堆可以做到O(VlogV+E)●若要输出路径,则设置prev数组记录每个节点的前趋点,在d[i]更新时更新prev[i]4 23 150200200 100080005000v Dist[v]0 01234 50100001000300025025082505250源点0加⼊P后:Dijkstra's AlgorithmDijkstra 算法也适⽤于⽆向图。

但不适⽤于有负权边的图。

231-234d[1,2] = 2但⽤Dijkstra 算法求得 d[1,2] = 3有N个孩⼦(N<=3000)分糖果。

acm-icpc暑期课_数学

acm-icpc暑期课_数学

北京大学暑期课《ACM/ICPC竞赛训练》北京大学信息学院郭炜guo_wei@/guoweiofpku课程网页:/summerschool/pku_acm_train.htm信息科学技术学院《程序设计与算法》ACM/ICPC中的数学郭炜/林舒( a + b ) mod c =((a mod c) + (b mod c)) mod c( a * b ) mod c =((a mod c) * (b mod c)) mod c消去律:若 gcd(c,p) = 1,则ac ≡ bc mod p => a ≡ b mod p消去律证明:ac ≡ bc mod p => ac = bc + kp => c(a-b) = kpc和p没有除1以外的公因子 =>1) c能整除k 或 2) a = b如果2不成立,则c|kpc和p没有公因子 => c|k,所以k = ck'=> c(a-b)=kp可以表示为c(a-b) =ck'p因此a-b = k'p,得出a ≡ b mod pint Pow(int a,int b){ //快速求a^b ,复杂度 log(b)if(b == 0)return 1;if(b & 1) { //b是奇数return a * Pow(a,b-1);}else {int t = Pow(a,b/2);return t * t;}}int Pow(int a,int b){ //快速求a^b ,复杂度 log(b) int result = 1;int base = a;while(b) {if( b & 1)result *= base;base *= base;b >>= 1;}return result;}快速幂取模int PowMod(int a,int b,int c){//快速求 a^b % c ,要避免计算中间结果溢出int result = 1;int base = a%c;while(b) {if( b & 1)result = (result * base)%c;base = (base * base) % c;b >>= 1;}return result;}Sn= a+a2+...+a n要求 Snmod p如果用公式算,可能溢出,因此用二分法求1) 若 n是偶数Sn= a+...+a n/2 + a n/2+1 + a n/2+2 +...+ a n/2+n/2 =(a+...+a n/2) + a n/2(a+...+a n/2)=Sn/2+ a n/2Sn/2=(1+a n/2)Sn/22) 若n是奇数= a+...+a(n-1)/2 + a(n-1)/2+1 +...Sn+ a(n-1)/2+(n-1)/2 + a(n-1)/2+(n-1)/2 + 1 =S+ a(n-1)/2(a+...+a(n-1)/2)+a n (n-1)/2+a n=(1+a(n-1)/2)S(n-1)/2等比数列二分求和取模int PowSumMod(int a,int n,int p){// return (a+ a^2 + ... + a^n) Mod p;if( n == 1)return a%p;if( n %2 == 0)return (1+PowMod(a,n/2,p))*PowSumMod(a,n/2,p) % p;elsereturn ((1+PowMod(a,(n-1)/2,p)) * PowSumMod(a,(n-1)/2,p) + PowMod(a,n,p)) % p;}POJ3233 Matrix Power Series矩阵快速幂+等比数列二分求和取模给一个n×n的整数矩阵A和正整数k,m, 令S = A + A2 + A3+ … +A k求 S mod m (S的每个都 mod m)n (n≤ 30),k (k≤ 109) and m (m < 104).struct Matrix{T a[32][32];int r; //行列数Mat(int rr):r(rr) { }void MakeI() { //变为单位矩阵memset(a,0,sizeof(a));for(int i = 0;i < r; ++i)a[i][i] = 1;}};Matrix Pow(const Matrix & m,int k,int p){ //求m k mod pint r = m.r;Matrix result(r);result.MakeI(); //MakeI是将result变为单位矩阵Matrix base = m;while(k) {if( k & 1)result = Product(result,base,p); //result*base mod pk >>= 1;base = Product(base,base,p);}return result;} 14欧几里得算法求最大公约数int Gcd(int a,int b){if( b == 0)return a;return Gcd(b,a%b);}最小公倍数:lcm(a,b) = a*b/gcd(a,b)ax+by=gcd(a,b) 有整数解(x,y)<=>bx+(a%b)y = gcd(a,b) 有整数解(x1,y1),且x = y1, y = x1-[a/b]*y1因此,可以在求gcd(a,b)的同时,对 ax+by=gcd(a,b)求解int GcdEx(int a,int b,int &x ,int & y) //求 ax+by=gcd(a,b)的整数解,返回gcd(a,b) {if( b == 0) {x = 1;y = 0;return a;}int x1,y1;int gcd = GcdEx(b,a%b,x1,y1);x = y1;y = x1 - a/b * y1;return gcd;}• ax+by=c 有解的充要条件是 gcd(a,b)|c•设 d = gcd(a,b), k = c/d,ax+by = d的解是 (x1,y1) 则ax+by = c的解集是:x = k*x1 + t*(b/d)y = k*y1 – t*(a/d) t为任意整数18•求ax≡c(mod b)等价于求 ax+by = c •设 d = gcd(a,b), k = c/d,ax+by = d的解是 (x1,y1) 则•ax≡c(mod b) 的解集是:x = k*x1 + t*(b/d) t为任意整数其中模b不同的解共有 d 个,为:x = k*x1 + t*(b/d) t=0,1,..d-1•求ax≡c(mod b) 的最小非负整数解:令 ans = k * x1;s = b/d;则 x = ans + t*s t为任意整数则最小非负整数解是:(ans%s + s)%s•对下面的循环:for (variable = A; variable != B; variable += C)statement;A,B,C和variable都是K(K<=32)比特的无符号数,+=运算的结果也是K比特的无符号数,给定 A,B,C和K,问循环执行多少次。

《图论与网络流》课件

《图论与网络流》课件

最ቤተ መጻሕፍቲ ባይዱ流最小割定理
总结词
最大流最小割定理是图论中一个重要的定理,它指出在一个有向图中,从源点到汇点的 最大流等于最小割的容量。
详细描述
最大流最小割定理是解决网络流问题的重要理论依据,它提供了一种将最大流问题转化 为最小割问题的思路。通过求解最小割问题,可以找到一个割点集合,使得从源点到汇 点的流量等于该割的容量,从而得到最大流。在实际应用中,最大流最小割定理可以应
感谢您的观看
THANKS
02
图论中的基本问题
欧拉路径与欧拉回路
欧拉路径
一个路径是图中的一条边序列, 使得每条边只经过一次,起点和
终点是同一点。
欧拉回路
一个路径是图中的一条边序列,使 得每条边只经过一次,起点和终点 是同一点,且所有节点均不重复。
总结
欧拉路径和回路是图论中的基本概 念,它们在计算机科学、运筹学、 电子工程等领域有广泛应用。
最小割算法
01
最小割算法是图论中求解最小割问题的算法,旨在将图划分为两个不 相交的子集,使得两个子集之间的边权值之和最小。
02
最小割问题与最大流问题是互补的,一个问题的解可以通过另一个问 题的解得到。
03
最小割算法的实现通常基于最大流算法,通过求解一系列最大流问题 来逼近最小割问题的解。
04
最小割算法的时间复杂度也取决于所选的算法和图的具体结构,一般 在多项式时间内可求解。
最小费用流算法
最小费用流问题考虑了流的代价 ,即每条边的容量和代价,要求 在满足流量限制的前提下,总代 价最小。
最小费用流算法的基本思想是通 过不断优化流的路径和代价来逼 近最小费用流的解。
最小费用流算法是图论中求解最 小费用流问题的算法,旨在找到 从源点到汇点具有最小费用的流 。

2015北大ACM暑期集训资料-组合数学、数论

2015北大ACM暑期集训资料-组合数学、数论

线性同余方程
已知 a, b, m,求解 ax = b (mod m)。 等价于存在一个整数 k 使得 ax + mk = b。
乘法逆元
已知 a, m,且 (a, m) = 1,求解 ax = 1 (mod m)。 借助上页方法求得的 x 即为 a 的乘法逆元,记作 a-1。 容易证明在 [0, m – 1] 中,a-1 唯一。

WIN 节点:当前玩家可以取得胜利。后继有一个 LOSE 节点。 LOSE 节点:当前玩家无法取得胜利。后继全部为 WIN 节点。
mex 函数
mex(S) 的定义:S 中未出现的最小非负整数,其中 S
是一个非负整数集。
SG 函数
对于一个状态 s,SG 函数的定义为
mex({SG(s’): (s, s’)∈E})

运用归纳法证明。
翻硬币游戏
有一列硬币,有些正面向上,有些背面向上。 每次选择一枚正面向上的硬币,将其翻转;然后可以
选择一枚它右边的硬币翻转,也可以不选择。
谁先不能操作 Blah blah blah blah blah。
翻硬币游戏(续)
将每枚正面向上的硬币看做一个子游戏。 子游戏的操作:将硬币移除,或者移到右边某个位置。 咦,不是说翻转吗?第二步将反面向上的硬币翻过来
k + 1。
翻硬币游戏各种加强版
将一枚正面向上的硬币翻转过来之后,右面可以按照某种
规则选择若干枚硬币翻过来。

1~2 枚硬币
一列距离相等的硬币
……
相当于游戏的后继可以是一个和游戏。 可以通过暴力/预处理/打表/猜等手段,确定某一位置上硬
币的 SG 值。
Anti-SG 游戏

2010北大ACM暑期讲义数学题

2010北大ACM暑期讲义数学题

常见置换的循环数
计算置换的循环数,是这一算法的瓶颈.如果能 够快速计算出各置换的循环数,就可以大大提 高程序的运行效率 旋转:n个点顺时针(或逆时针)旋转i个位置的置 换,循环数为gcd(n,i) 翻转:
n为偶数时,
对称轴不过顶点:循环数为n/2 对称轴过顶点:循环数为n/2+1
置换群
以置换为元素的群 置换群G={a1,a2,...,a|G|} 例子中G内共有6个置换 123456 123456 123456 123456 612345 561234 123456 123456 123456 456123 345612 234561
循环
在一个置换下,x1->x2,x2->x3,...,xn->x1,这 样x1,x2,...,xn就构成了一个循环 定义ck为在置换ak下的循环总数 例子中: c1=6,c2=1,c3=2,c4=3,c5=2,c6=1
Polya定理
设G={a1,a2,...,a|G|}是N={1,2,...,N}上的置 换群,现用m种颜色对这N个点染色,则不 同的染色方案数为 S=(mc1+mc2+...+mc|G|)/|G| 证明比较复杂,略
利用Polya定理 解决组合计数问题的步骤
写出置换群 123456 123456 123456 123456 612345 561234 123456 123456 123456 456123 345612 234561 求出每个置换的循环数 c1=6,c2=1,c3=2,c4=3,c5=2,c6=1 计算染色方案 S=(26+21+22+23+22+21)/6=14
解二元模线性方程

北京大学 acm程序设计 图论讲义

北京大学 acm程序设计 图论讲义
22
for (w=G->first(v); w<G->n(); w = G>next(v,w))
if (G->getMark(w) == UNVISITED) { G->setMark(w, VISITED); Q->enqueue(w); }
PostVisit(G, v); // Take action }}
Q Q
31
() ((1,1)) ((1,1) (2,3)) ((1,1) (2,4)) ((1,1) (2,4) (3.2))
Q Q
Q
32
() ((1,1)) ((1,1) (2,3)) ((1,1) (2,4)) ((1,1) (2,4) (3.2))
Q Q
33
Q () ((1,1)) ((1,1) (2,3)) ((1,1) (2,4)) ((1,1) (2,4) (3.2))
求解算法
穷举法 贪心法 深度/广度优先搜索
图和树的搜索 回溯法(深度优先)
递归
分治
动态规划法
55
谢谢!
56
49
动态规划法的思想
自底向上构造 在原问题的小子集中计算 每一步列出局部最优解,并用一张
表保留这些局部最优解,以避免重 复计算 子集越来越大,最终在问题的全集 上计算,所得出的就是整体最优 解。
50
Fib(1)=Fib(2)=1
Fibonacci数列 Fib(n)=Fib(n-1) + Fib (n-2)
23
八数码 深度优先搜索
1
23 184 765
2
c
3
283 164 75
283 14 765

大学生程序设计acm辅导教程完整版

大学生程序设计acm辅导教程完整版

国际大学生程序设计竞赛辅导教程郭嵩山崔昊吴汉荣陈明睿著北京大学出版社前言ACM 国际大学生程序设计竞赛(ACM International Collegiate Programming Contest,简称ACM/ICPC)是由国际计算机界历史最悠久、颇具权威性的组织ACM 学会(Association for Computer Machinery)主办,是世界上公认的规模最大、水平最高的国际大学生程序设计竞赛,其目的旨在使大学生运用计算机来充分展示自已分析问题和解决问题的能力。

该项竞赛从 1970 年举办至今已历 25 届,因历届竞赛都荟萃了世界各大洲的精英,云集了计算机界的“希望之星”,而受到国际各知名大学的重视,并受到全世界各著名计算机公司的高度关注,成为世界各国大学生最具影响力的国际级计算机类的赛事,ACM 所颁发的获奖证书也为世界各著名计算机公司、各知名大学所认可。

该项竞赛分区域预赛和世界决赛两个阶段进行,各预赛区第一名自动获得参加世界决赛的资格,世界决赛安排在每年的 3~4 月举行,而区域预赛安排在上一年的 9 月~12 月在各大洲举行。

ACM/ICPC 的区域预赛是规模很大,范围很广的赛事,近几年,全世界有 1000 多所大学,近 2000 支参赛队在六大洲的 28~30 个赛站中争夺世界决赛的 60 个名额,其激烈程度可想而知。

与其他编程竞赛相比,ACM/ICPC 题目难度更大,更强调算法的高效性,不仅要解决一个指定的命题,而且必需要以最佳的方式解决指定的命题;它涉及知识面广,与大学计算机系本科以及研究生如程序设计、离散数学、数据结构、人工智能、算法分析与设计等相关课程直接关联,对数学要求更高,由于采用英文命题,对英语要求较高,ACM/ICPC 采用3 人合作、共用一台电脑,所以它更强调团队协作精神;由于许多题目并无现成的算法,需要具备创新的精神,ACM/ICPC 不仅强调学科的基础,更强调全面素质和能力的培养;由于ACM/ICPC 是采用5 小时全封闭式竞赛,参赛队员与外界完全隔离,完全独立完成,没有任何水份,是其实际能力的真实表露,其成绩可信度甚高;但ACM/ICPC 又是一种“开卷考试”,可以带任何书籍、资料甚至源程序代码清单(但不能带软盘),不需要去死背算法,而强调的是算法的灵活运用;与其它计算机竞赛(如软件设计,网站设计等)相比,ACM/ICPC 有严谨而客观的评判规则(严格的数据测试),排除了因评委的主观因素而造成评审不公平的现象,所以,ACM/ICPC 对成绩的争议较少,大家比较心服口服。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

现在假设每条边的容量都是整数
这个算法每次都能将流至少增加1 由于整个网络的流量最多不超过 图中所有的边的容 量和C,从而算法会结束 现在来看复杂度 找增广路径的算法可以用dfs, 复杂度为边数m+顶 点数n Dfs 最多运行C次 所以时间复杂度为C*(m+n) =C* n^2
这个算法实现很简单 但是注意到在图中C可能很大很大 比如说下面这张图

a
100 s 100 100
100 100 b
t
如果我们沿着s-a-b-t路线走 仅能得到一个100的流
a 100 s 100 100
100
100
t
实际上此图存在流量 为200的流
b
问题出在过早地认为边a → b上流量不为0,因而“ 封锁”了流量继续增大的可能。 一个改进的思路:应能够修改已建立的流网络,使得 “不合理”的流量被删掉。 一种实现:对上次dfs时找到的流量路径上的边,添 加一条“反向”边,反向边上的容量等于上次dfs时 找到的该边上的流量,然后再利用“反向”的容量和 其他边上剩余的容量寻找路径。
已经证明这种算法的复杂度上限为nm2 (n是 点数,m是边数)
Poj 1273 Drainage Ditches
赤裸裸的网络流题目。给定点数,边数,每条 边的容量,以及源点,汇点,求最大流。
Sample Input Sample Output 54 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10
#define INFINITE 999999999 //Poj 1273 Drainage Ditches 的 Dinic算法 int G[300][300]; bool Visited[300]; int Layer[300]; int n,m; //1是源点,m是汇点 bool CountLayer() { int layer = 0; deque<int>q; memset(Layer,0xff,sizeof(Layer));//都初始化成-1 Layer[1] = 0; q.push_back(1); while( ! q.empty()) { int v = q.front(); q.pop_front(); for( int j = 1; j <= m; j ++ ) { if( G[v][j] > 0 && Layer[j] == -1 ) { //Layer[j] == -1 说明j还没有访问过 Layer[j] = Layer[v] + 1; if( j == m ) //分层到汇点即可 return true; else q.push_back(j); } } } return false; }
a
n
b
为什么添加反向边(取消流)是有效的?
构建残余网络时添加反向边a->b,容量是n,增 广的时候发现了流量n-k,即新增了n-k的流量。 这n-k的流量,从a进,b出,最终流到汇
a n-k
n
b
现要证明这2n-k的从流量,在原图上确实是 可以从源流到汇的。
a n-k
n
b
把流入b的边合并,看做一条,把流出a的边 也合并,同理把流入a和流出b的边也都合并。
a
100
100 100 t
第一次dfs后:
s 100
b
100
第一次dfs后,添加反向边得到的新图:
a 100 s 100
100 100
b 100
t
这样我们第二次dfs搜索的时候就可以在新的网 络里找是两条路径 的合并
a
100 s
100 b 100
100
t 100
如果回溯到源点而且无法继续往下走了,DFS结束。
因此,一次DFS过程中,可以找到多条增广路径。
DFS结束后,对残余网络再次进行分层,然后再进行DFS 当残余网络的分层操作无法算出汇点的层次(即BFS到达 不了汇点)时,算法结束,最大流求出。 一般用栈实现DFS,这样就能从栈中提取出增广路径。
Dinic 复杂度是 n*n*m (n是点数,m是边数)
while( ! q.empty()) { v = q.front(); q.pop_front(); for( i = 1;i <= m;i ++) {
if( G[v][i] > 0 && Visited[i] == 0) { //必须是依然有容量的边,才可以走 Prev[i] = v; Visited[i] = 1; if( i == m ) { bFindPath = true; q.clear(); break; } else q.push_back(i); } }
解决最大流的Ford-Fulkerson算 法
基本思路很简单,每次用dfs从源到汇找一 条可行路径, 然后把这条路塞满。这条 路径上容量最小的那条边的容量,就是这 次dfs所找到的流量。然后对于路径上的 每条边,其容量要减去刚才找到的流量。 这样,每次dfs都可能增大流量,直到某次 dfs找不到可行路径为止,最大流就求出 来了 这个想法是否正确?
int Dinic() { int i; int s; int nMaxFlow = 0; deque<int> q;//DFS用的栈 while( CountLayer() ) { //只要能分层 q.push_back(1); //源点入栈 memset(Visited,0,sizeof(Visited)); Visited[1] = 1; while( !q.empty()) { int nd = q.back(); if( nd == m ) { // nd是汇点 //在栈中找容量最小边 int nMinC = INFINITE; int nMinC_vs; //容量最小边的起点 for( i = 1;i < q.size(); i ++ ) { int vs = q[i-1]; int ve = q[i]; if( G[vs][ve] > 0 ) { if( nMinC > G[vs][ve] ) { nMinC = G[vs][ve]; nMinC_vs = vs; } } }
Dinic 算法
先利用 BFS对残余网络分层
s -1
-1
1 2
3
2
-1
1
2 3
t
2
-1
2
-1
1
3
一个节点的“层”数,就是源点到它最少要经过的边数。
1
3
-1
Dinic 算法
利用 BFS对残余网络分层,分完层后,利用DFS从前 一层向后一层反复寻找增广路。
1
1 1 2
3 2
s 0
2
t
2
2
3
3
n a n-k
n-k
n
n-k
b n
在原图上可以如下分配流量,则能有2n-k从 源流到汇点:
n a
n-k
n a n-k
n-k
k
n
n-k
b n
n-k
b n
没有严格证明,只给一个感性认识。几条反 向边相连的各种复杂情况也可以类似分析。
Ford-Fulkerson算法
求最大流的过程,就是不断找到一条源到汇 的路径,然后构建残余网络,再在残余网络 上寻找新的路径,使总流量增加,然后形成 新的残余网络,再寻找新路径…..直到某个 残余网络上找不到从源到汇的路径为止,最 大流就算出来了。 每次寻找新流量并构造新残余网络的过程, 就叫做寻找流量的“增广路径”,也叫“增 广”
50
#include <iostream> #include <queue> using namespace std; int G[300][300]; int Prev[300]; //路径上每个节点的前驱节点 bool Visited[300]; int n,m; //m是顶点数目,顶点编号从1开始 1是源,m是汇, n是 边数 unsigned Augment() { int v; int i; deque<int> q; memset(Prev,0,sizeof(Prev)); memset(Visited,0,sizeof(Visited)); Prev[1] = 0; Visited[1] = 1; q.push_back(1); bool bFindPath = false; //用bfs寻找一条源到汇的可行路径
}
if( ! bFindPath) return 0; int nMinFlow = 999999999; v = m; //寻找源到汇路径上容量最小的边,其容量就是此次增 加的总流量 while( Prev[v] ) { nMinFlow = min( nMinFlow,G[Prev[v]][v]); v = Prev[v]; } //沿此路径添加反向边,同时修改路径上每条边的容量 v = m; while( Prev[v] ) { G[Prev[v]][v] -= nMinFlow; G[v][Prev[v]] += nMinFlow; v = Prev[v]; } return nMinFlow; }
第二次dfs搜索又找到了一个流量为100的流,加 上第一次搜索得到的流量为100的流,总流量上 升到200
a
100
s 100
t
100
b
再对第二次dfs后的图添加反向边,变成:
a
100
s 100
100 t
100 b
100
在此图上再次进行dfs,已经找不到路径了,所以 流量无法再增加,最大流就是200
要求出最大流中每条边的流量,怎么办?
要求出最大流中每条边的流量,怎么办?
相关文档
最新文档