ACM比赛模板.docx

上传人:b****3 文档编号:1159874 上传时间:2022-10-18 格式:DOCX 页数:91 大小:41.90KB
下载 相关 举报
ACM比赛模板.docx_第1页
第1页 / 共91页
ACM比赛模板.docx_第2页
第2页 / 共91页
ACM比赛模板.docx_第3页
第3页 / 共91页
ACM比赛模板.docx_第4页
第4页 / 共91页
ACM比赛模板.docx_第5页
第5页 / 共91页
点击查看更多>>
下载资源
资源描述

ACM比赛模板.docx

《ACM比赛模板.docx》由会员分享,可在线阅读,更多相关《ACM比赛模板.docx(91页珍藏版)》请在冰豆网上搜索。

ACM比赛模板.docx

ACM比赛模板

1.最小生成树

要连通n个城市需要n-1条边线路。

可以把边上的权值解释为线路的造价。

则最小生成树表示使其造价最小的生成树。

prim算法(矩阵形式):

#defineinf0x3f3f3f3f

intprim(intn,intsta)//n表示有n个顶点,sta表从sta这个顶点出发生成最小生成树

{

   intmark[M],dis[M];

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

   for(i=0;i

   {

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

       mark[i]=0;

   }

   mark[sta]=1;         //sta这个顶点加入最小生成树中

   for(i=1;i

   {       //只有n-1条边

       intmin=inf;      //inf表无穷大

       for(j=0;j

           if(!

mark[j]&&dis[j]

               min=dis[j],flag=j;

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

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

       for(j=0;j

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

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

   }

   returnsum;      //返回边权总和

}

prim算法(边表形式):

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

{

  //intfrm;

   intto,w,nxt;

}edge[M];

intvis[M],head[M],dis[M];

voidaddedge(intcu,intcv,intcw)//生成边的函数

{

   //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++;

}

intprim(intn,intsta)//n为顶点数量,sta为起点

{

   intsum=0;

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

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

   for(i=head[sta];i!

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

   {

       intv=edge[i].to;

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

   }

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

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

   while(m--)

   {

       intmin=inf;

       for(i=0;i

           if(!

vis[i]&&dis[i]

               flag=i,min=dis[i];

       sum+=dis[flag];

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

       for(i=head[flag];i!

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

       {            

           intv=edge[i].to;

           if(edge[i].w

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

       }

   }

   returnsum;//返回边权总和

}

intmain()

{

   e=0;                 //记得初始化

   memset(head,-1,sizeof(head));

   scanf("%d%d%d",&a,&b,&w);

   addedge(a,b,w);

   .....

   .....

   prim(n,sta);

   return0;

}

Kruskal算法:

structEdge

{

   intv1,v2,w;

}edge[M],tree[M];          //w为v1顶点到v2顶点的边权

/*

intFind(intparent[],intu)//第1种写法

{

   inttmp=u;

   while(paren[tmp]!

=-1)

       tmp=parent[tmp];

   returntmp;

}

*/

intFind(intu) //第2种写法

{

   if(u!

=parent[u])

       parent[u]=Find(paren[u]);

   returnparent[u];

}

boolcmp(Edgea,Edgeb)

{

   returna.w

}

intKruskal()//parent[]表示集合

{

   intparent[M];

   inti,j,sum,vf1,vf2;

   sort(edge,edge+E,cmp);

 // memset(parent,-1,sizeof(parent));//对应第1种并查集的初始化

   for(i=0;i

       parent[i]=i;

   sum=i=j=0;

   while(i

   {

       vf1=Find(parent,edge[i].v1); //找这两个点的祖先

       vf2=Find(parent,edge[i].v2);

       if(vf1!

=vf2)//若两个点的祖先不同,说明不在同一集合

       {

           parent[vf2]=vf1;//把vf2点加到vf1点的集合中

           tree[j++]=edge[i];//把边加到tree[]数组中,这句题目没要求可忽略之

           sum+=edge[i].w;   //sum加上其边权

       }

       i++;

   }

   returnsum;

}

最小生成树--Kruskal算法:

运用数组存点与边的权值

#include

#include

#include

#defineN150

usingnamespacestd;

intm,n,u[N],v[N],w[N],p[N],r[N];

intcmp(constinti,constintj){returnw[i]

intfind(intx){returnp[x]==x?

x:

p[x]=find(p[x]);}

intkruskal()

{

intcou=0,x,y,i,ans=0;

for(i=0;i

for(i=0;i

sort(r,r+m,cmp);

for(i=0;i

{

inte=r[i];x=find(u[e]);y=find(v[e]);

if(x!

=y){ans+=w[e];p[x]=y;cou++;}

}

if(cou

returnans;

}

intmain()

{

inti,ans;

while(scanf("%d%d",&m,&n)!

=EOF&&m)

{

for(i=0;i

{

scanf("%d%d%d",&u[i],&v[i],&w[i]);

}

ans=kruskal();

if(ans)printf("%d\n",ans);

elseprintf("?

\n",ans);

}

return0;

}

2.最短路算法

①DIJK

C++代码 

1.#define inf 0x3fffffff  

2.#define M 105  

3.  

4.int dist[M], map[M][M], n;  

5.bool mark[M];  

6.  

7.void init ()  

8.{  

9.    int i, j;  

10.    for (i = 1; i <= n; i++)    //i==j的时候也可以初始化为0,只是有时候不合适  

11.        for (j = 1; j <= n; j++)  

12.            map[i][j] = inf;  

13.}  

14.  

15.void dijk (int u)  

16.{  

17.    int i, j, mins, v;  

18.    for (i = 1; i <= n; i++)  

19.    {  

20.        dist[i] = map[u][i];  

21.        mark[i] = false;  

22.    }  

23.    mark[u] = true;  

24.    dist[u] = 0;    //既然上面的map当i==j时不是0,就要这句  

25.    while 

(1)  

26.    {  

27.        mins = inf;  

28.        for (j = 1; j <= n; j++)  

29.            if (!

mark[j] && dist[j] < mins)  

30.          

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1