ACM比赛模板

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

目录

1.最小生成树 (2)

2.最短路算法 (7)

3.素数打表 (11)

4.最大匹配 (12)

5.线段树(敌兵布阵) (14)

6.线段树(逆序树) (16)

7.树形dp (18)

8.树状数组(段跟新) (20)

9.Kmp模板 (22)

10.线段树(点跟新) (26)

11.强连通 (28)

12.最小割 (31)

13.单源最短路(spfa) (34)

14.三分查找 (36)

15.字典树(统计难题) (38)

16.最大流入门题1273 (40)

17.状态压缩 (43)

18.匈牙利(HDU 2063)(最大匹配) (45)

19.凸包(HDU1348) (47)

20.树状数组(HDU1166) (50)

21.强连通 (52)

22.前向星 (55)

23.矩阵 (58)

24.并查集 (60)

25. SORT (61)

26. STL (63)

27. LCA (HDU 2874) (67)

28. 01背包 (70)

29. 状态压缩代码: (72)

30. 快速幂 (74)

31.矩阵快速幂 (75)

32.GCD & LCM (77)

33.ACM小技巧: (78)

34. /** 大数(高精度)求幂**/ (80)

35. /** 大数除法与求余**/ (82)

36. /** 大数阶乘**/ (84)

37. /** 大数乘法**/ (85)

38. /** 大数累加**/ (86)

1.最小生成树

要连通n个城市需要n-1条边线路。可以把边上的权值解释为线路的造价。则最小生成树表示使其造价最小的生成树。

prim算法(矩阵形式):

#define inf 0x3f3f3f3f

int prim(int n,int sta)//n表示有n个顶点,sta表从sta这个顶点出发生成最小生成树{

int mark[M],dis[M];

int i,sum = 0; //sum是总的最小生成树边权值

for (i = 0;i < n;i ++) //初始化dis[i] 表从顶点sta到点i的权值 {

dis[i] = mat[sta][i];

mark[i] = 0;

}

mark[sta] = 1; //sta 这个顶点加入最小生成树中 for (i = 1;i < n;i ++) //循环n-1次,每次找出一条最小权值的边 n个点的图

{ //只有n-1条边

int min = inf; //inf 表无穷大

for (j = 0;j < n;j ++)//找出当前未在最小生成树中边权最小的顶点

if (!mark[j] && dis[j] < min)

min = dis[j],flag = j;

mark[flag] = 1; //把该顶点加入最小生成树中

sum += dis[flag]; //sum加上其边权值

for (j = 0;j < n;j ++) //以falg为起点更新到各点是最小权值

if (dis[j] > mat[flag][j])

dis[j] = mat[flag][j];

}

return sum; //返回边权总和

}

prim算法(边表形式):

struct Edge//frm为起点,to为终点,w为边权,nxt指向下一个顶点

{

// int frm;

int to,w,nxt;

}edge[M];

int vis[M],head[M],dis[M];

void addedge (int cu,int cv,int cw)//生成边的函数

{

//edge[e].frm = cu;

edge[e].to = cv;

edge[e].w = cw;

edge[e].nxt = head[cu];

head[cu] = e ++;

//edge[e].frm = cv;

edge[e].to = cu;

edge[e].w = cw;

edge[e].nxt = head[cv];

head[cv] = e ++;

}

int prim(int n,int sta) //n为顶点数量,sta为起点

{

int sum = 0;

memset(dis,0x3f,sizeof(dis));

memset(vis,0,sizeof(vis));

for (i = head[sta];i != -1;i = edge[i].nxt)//遍历与sta点相连的所有顶点 {

int v = edge[i].to;

dis[v] = edge[i].w;

}

vis[sta] = 1; //加入到最小生成树中

int m = n - 1; //只生成n-1条边,所以循环n-1次

while (m --)

{

int min = inf;

for (i = 0;i < n;i ++)//找出当前边权最小的边

if (!vis[i]&&dis[i] < min)

flag = i,min = dis[i];

sum += dis[flag];

vis[flag] = 1;//加入到最小生成树中

for (i = head[flag];i != -1;i = edge[i].nxt) //更新与flag顶点相连的点的dis

{

int v = edge[i].to;

if (edge[i].w < dis[v])

dis[v] = edge[i].w;

}

}

return sum; //返回边权总和

}

相关文档
最新文档