当前位置:首页 » 操作系统 » 连通器算法

连通器算法

发布时间: 2022-06-05 07:50:39

A. 已知一个图的连接矩阵,判断给定两个节点是否连通的算法思想

用深度优先搜索,从给定节点开始,遍历一遍所有节点,如果另一个节点遍历到了,就连同,反之不连通
如果要算出所有节点,则每个节点都执行一次DFS,把结果存在一个二维数组里,就能查询了!

B. 在n个城市之间建设网络,只需保证连通即可,求最经济的架设方案 多种算法求解 求完整的程序代码……

我给出prim和kruscal两种实现吧,其中prim用到了堆,用于每次选出剩余边中的权值最小的边,而kruscal用到了并查集,用于保存已求得的连通分量。我的题目是hdoj1863,跟上面要求基本相同,这两种实现都已AC。下面是代码:
//prim实现

#include<iostream>
#include<algorithm>
#include<limits.h>
using namespace std;

struct Node
{
int to;
int cost;
};

int w[102][102];
Node heap[102];
int N,M,res,size;

void down(int p)
{
Node n=heap[p];
for(int q=p<<1;q<=size;q<<=1)
{
if(q<size&&heap[q+1].cost!=-1&&heap[q].cost>heap[q+1].cost)
q++;
if(heap[q].cost==-1||n.cost!=-1&&n.cost<=heap[q].cost)
{
break;
}
heap[p]=heap[q];
p=q;
}
heap[p]=n;
}

void up(int p)
{
if(heap[p].cost==-1)
return;
Node n=heap[p];
for(int q=p>>1;q>=1;q>>=1)
{
if(heap[q].cost!=-1&&heap[q].cost<=n.cost)
break;
heap[p]=heap[q];
p=q;
}
heap[p]=n;
}

void build()
{
for(int i=size>>1;i>0;i--)
down(i);
}

void prim()
{
for(int i=2;i<=M;i++)
{
heap[i-1].cost=w[1][i];
heap[i-1].to=i;
}
size=M-1;
build();
res=0;
for(int i=1;i<M;i++)
{
if(heap[1].cost==-1)
{
res=-1;
return;
}
res+=heap[1].cost;;
int v=heap[1].to;
heap[1]=heap[size--];
down(1);
for(int j=1;j<=size;j++)
{
if(w[v][heap[j].to]!=-1)
{
if(w[v][heap[j].to]<heap[j].cost||heap[j].cost==-1)
{
heap[j].cost=w[v][heap[j].to];
up(j);
}
}
}
}
}

int main()
{
while(scanf("%d%d",&N,&M)!=EOF&&N)
{
memset(w,255,sizeof(w));
int a,b,cost;
memset(w,255,sizeof(w));
for(int i=1;i<=N;i++)
{
scanf("%d%d%d",&a,&b,&cost);
w[a][b]=w[b][a]=cost;
}
prim();
if(res==-1)
printf("?\n");
else
printf("%d\n",res);
}
}
//kruscal实现

#include<iostream>
#include<algorithm>
usingnamespacestd;

struct Edge
{
intu,v,w;
};

Edge edges[5000];
int parent[102];
intN,M,res;

int find(int v)
{
if(parent[v]>0)
parent[v]=find(parent[v]);
return parent[v]>0?parent[v]:v;
}

voinion_set(inta,int b)
{
if(parent[a]<=parent[b])
{
parent[a]+=parent[b];
parent[b]=a;
}
else
{
parent[b]+=parent[a];
parent[a]=b;
}
}

intcmp(Edge e1,Edge e2)
{
return e1.w<e2.w;
}

Void kruscal()
{
res=0;
memset(parent,255,sizeof(parent));
sort(edges,edges+N,cmp);
intloc=0;
int a,b,p1,p2,count=0;
bool flag=true;
while(loc<N)
{
do
{
loc++;
if(loc>N)
{
flag=false;
break;
}
a=edges[loc].u;
b=edges[loc].v;
p1=find(a);
p2=find(b);
}while(p1==p2);
if(!flag)
break;
res+=edges[loc].w;
union_set(p1,p2);
count++;
}
if(count<M-1)
res=-1;
}

int main()
{
while(scanf("%d%d",&N,&M)!=EOF&&N)
{
for(inti=1;i<=N;i++)
scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].w);
kruscal();
if(res==-1)
printf("?\n");
else
printf("%d\n",res);
}
}

C. 强连通分量(Kosaraju算法)

{ //判断各个强连通分量是否为出度为0的分量 for(int t = 0; t

D. 连通图的深度优先遍历算法

这个第一个点是随机的。只是看你怎么储存的。如果你把v的邻接顶点用数组保存,那么它在数组的最前边。用指针的话,就指向下一个紧接的位置。

E. connected component是什么意思

connected component
英[kəˈnektɪd kəmˈpəunənt]
美[kəˈnɛktɪd kəmˈponənt]
连通分支[量];
[例句]The crux of the algorithm comes in determining whether a node is the root of a strongly connected component.
算法的关键是判断一个结点是否是强连通分量的根。

F. 强连通分量的Gabow算法思路

这个算法其实就是Tarjan算法的变异体,我们观察一下,只是它用第二个堆栈来辅助求出强连通分量的根,而不是Tarjan算法里面的indx[]和mlik[]数组。那么,我们说一下如何使用第二个堆栈来辅助求出强连通分量的根。
我们使用类比方法,在Tarjan算法中,每次mlik[i]的修改都是由于环的出现(不然,mlik[i]的值不可能变小),每次出现环,在这个环里面只剩下一个mlik[i]没有被改变(深度最低的那个),或者全部被改变,因为那个深度最低的节点在另一个环内。那么Gabow算法中的第二堆栈变化就是删除构成环的节点,只剩深度最低的节点,或者全部删除,这个过程是通过出栈来实现,因为深度最低的那个顶点一定比前面的先访问,那么只要出栈一直到栈顶那个顶点的访问时间不大于深度最低的那个顶点。其中每个被弹出的节点属于同一个强连通分量。那有人会问:为什么弹出的都是同一个强连通分量?因为在这个节点访问之前,能够构成强连通分量的那些节点已经被弹出了,这个对Tarjan算法有了解的都应该清楚,那么Tarjan算法中的判断根我们用什么来代替呢?想想,其实就是看看第二个堆栈的顶元素是不是当前顶点就可以了。
现 在,你应该明白其实Tarjan算法和Gabow算法其实是同一个思想的不同实现,但是,Gabow算法更精妙,时间更少(不用频繁更新mlik[])。 Gabow_Algorithm:
步骤1:
找一个没有被访问过的节点v,goto step2(v)。否则,算法结束。
步骤2(v):
将v压入堆栈stk1[]和stk2[]
对于v所有的邻接顶点u:
1) 如果没有访问过,则step2(u)
2) 如果访问过,但没有删除,维护stk2[](处理环的过程)
如果stk2[]的顶元素==v,那么输出相应的强连通分量 C++:#include<iostream>usingnamespacestd;constintMAXN=110;typedefintAdjTable[MAXN];//邻接表类型intn;intintm[MAXN];//标记进入顶点时间intbelg[MAXN];//存储强连通分量,其中belg[i]表示顶点i属于第belg[i]个强连通分量intstk1[MAXN];//辅助堆栈intstk2[MAXN];//辅助堆栈AdjTableadj[MAXN];//邻接表//深搜过程,该算法的主体都在这里voidVisit(intcur,int&sig,int&scc_num){inti;intm[cur]=++sig;stk1[++stk1[0]]=cur;stk2[++stk2[0]]=cur;for(i=1;i<=adj[cur][0];++i){if(0==intm[adj[cur][i]]){Visit(adj[cur][i],sig,scc_num);}elseif(0==belg[adj[cur][i]]){while(intm[stk2[stk2[0]]]>intm[adj[cur][i]]){--stk2[0];}}}if(stk2[stk2[0]]==cur){--stk2[0];++scc_num;do{belg[stk1[stk1[0]]]=scc_num;}while(stk1[stk1[0]--]!=cur);}}//Gabow算法,求解belg[1..n],且返回强连通分量个数,intGabow_StronglyConnectedComponent(){inti,sig,scc_num;memset(belg+1,0,sizeof(int)*n);memset(intm+1,0,sizeof(int)*n);sig=0;scc_num=0;stk1[0]=0;stk2[0]=0;for(i=1;i<=n;++i){if(0==intm[i]){Visit(i,sig,scc_num);}}returnscc_num;}Pascalproceretarjan(r:longint);varx,i,j:longint;begininc(timez);time[r]:=timez;low[r]:=timez;inc(top);zh[top]:=r;fori:=p1[r]top2[r]dobeginj:=e[i].y;iftime[j]=0thentarjan(j);iflow[j]<low[r]thenlow[r]:=low[j];end;iftime[r]=low[r]thenrepeatx:=zh[top];num[x]:=r;low[x]:=n+1;//这句话千万别忘了dec(top);untilx=r;end;

G. 连通器之所以液面相平是因为要保持各高度压强相等吗可如果封一段砌筑,那一段的压强都是相等的哦

你把因果颠倒了,静止状态下由于静压能的作用液面保持相平,封在液体中的气体往往是被压缩的p=Pa+pgh

H. 用C语言编写求有向图有多少连通图的算法(数据结构题目)

深度优先搜索。

http://www.cnblogs.com/dzkang2011/p/bfs_dfs.html

#include<iostream>
#include<cstdio>
usingnamespacestd;

#definemaxn100//最大顶点个数
intn,m;//顶点数,边数

structarcnode//边结点
{
intvertex;//与表头结点相邻的顶点编号
intweight=0;//连接两顶点的边的权值
arcnode*next;//指向下一相邻接点
arcnode(){}
arcnode(intv,intw):vertex(v),weight(w),next(NULL){}
arcnode(intv):vertex(v),next(NULL){}
};

structvernode//顶点结点,为每一条邻接表的表头结点
{
intvex;//当前定点编号
arcnode*firarc;//与该顶点相连的第一个顶点组成的边
}Ver[maxn];

voidInit()//建立图的邻接表需要先初始化,建立顶点结点
{
for(inti=1;i<=n;i++)
{
Ver[i].vex=i;
Ver[i].firarc=NULL;
}
}

voidInsert(inta,intb,intw)//尾插法,插入以a为起点,b为终点,权为w的边,效率不如头插,但是可以去重边
{
arcnode*q=newarcnode(b,w);
if(Ver[a].firarc==NULL)
Ver[a].firarc=q;
else
{
arcnode*p=Ver[a].firarc;
if(p->vertex==b)//如果不要去重边,去掉这一段
{
if(p->weight<w)
p->weight=w;
return;
}
while(p->next!=NULL)
{
if(p->next->vertex==b)//如果不要去重边,去掉这一段
{
if(p->next->weight<w);
p->next->weight=w;
return;
}
p=p->next;
}
p->next=q;
}
}
voidInsert2(inta,intb,intw)//头插法,效率更高,但不能去重边
{
arcnode*q=newarcnode(b,w);
if(Ver[a].firarc==NULL)
Ver[a].firarc=q;
else
{
arcnode*p=Ver[a].firarc;
q->next=p;
Ver[a].firarc=q;
}
}

voidInsert(inta,intb)//尾插法,插入以a为起点,b为终点,无权的边,效率不如头插,但是可以去重边
{
arcnode*q=newarcnode(b);
if(Ver[a].firarc==NULL)
Ver[a].firarc=q;
else
{
arcnode*p=Ver[a].firarc;
if(p->vertex==b)return;//去重边,如果不要去重边,去掉这一句
while(p->next!=NULL)
{
if(p->next->vertex==b)//去重边,如果不要去重边,去掉这一句
return;
p=p->next;
}
p->next=q;
}
}
voidInsert2(inta,intb)//头插法,效率跟高,但不能去重边
{
arcnode*q=newarcnode(b);
if(Ver[a].firarc==NULL)
Ver[a].firarc=q;
else
{
arcnode*p=Ver[a].firarc;
q->next=p;
Ver[a].firarc=q;
}
}

voidShow()//打印图的邻接表(有权值)
{
for(inti=1;i<=n;i++)
{
cout<<Ver[i].vex;

arcnode*p=Ver[i].firarc;
while(p!=NULL)
{
cout<<"->("<<p->vertex<<","<<p->weight<<")";
p=p->next;
}
cout<<"->NULL"<<endl;
}
}

voidShow2()//打印图的邻接表(无权值)
{
for(inti=1;i<=n;i++)
{
cout<<Ver[i].vex;
arcnode*p=Ver[i].firarc;
while(p!=NULL)
{
cout<<"->"<<p->vertex;
p=p->next;
}
cout<<"->NULL"<<endl;
}
}
#defineINF999999
boolvisited[maxn];//标记顶点是否被考察,初始值为false
intparent[maxn];//parent[]记录某结点的父亲结点,生成树,初始化为-1
intd[maxn],time,f[maxn];//时间time初始化为0,d[]记录第一次被发现时,f[]记录结束检查时
voiddfs(ints)//深度优先搜索(邻接表实现),记录时间戳,寻找最短路径
{
cout<<s<<"";
visited[s]=true;
time++;
d[s]=time;
arcnode*p=Ver[s].firarc;
while(p!=NULL)
{
if(!visited[p->vertex])
{
parent[p->vertex]=s;
dfs(p->vertex);
}
p=p->next;
}
time++;
f[s]=time;
}
voiddfs_travel()//遍历所有顶点,找出所有深度优先生成树,组成森林
{
for(inti=1;i<=n;i++)//初始化
{
parent[i]=-1;
visited[i]=false;
}
time=0;
for(inti=1;i<=n;i++)//遍历
if(!visited[i])
dfs(i);
cout<<endl;
}
intmain()
{
inta,b;
cout<<"Enternandm:";
cin>>n>>m;
Init();
while(m--)
{
cin>>a>>b;//输入起点、终点
Insert2(a,b);//插入操作
}
Show2();//邻接表
dfs_travel();//遍历
intcnt=0;//连通图个数
for(inti=1;i<=n;i++)
if(parent[i]==-1)
cnt++;
printf("%d ",cnt);
return0;
}
热点内容
怎么样解压qq文件 发布:2024-10-31 08:58:46 浏览:74
安卓国际服怎么加模组 发布:2024-10-31 08:47:40 浏览:670
天翼高清盒子怎么配置 发布:2024-10-31 08:41:42 浏览:924
建材直播脚本 发布:2024-10-31 08:34:26 浏览:241
数据库备份表 发布:2024-10-31 08:32:26 浏览:416
中国游戏服务器如何用 发布:2024-10-31 08:16:23 浏览:629
查看linux内存使用率 发布:2024-10-31 08:14:25 浏览:48
华为低配置怎么样弄深夜模式 发布:2024-10-31 08:13:32 浏览:521
光遇安卓高马尾什么时候复刻 发布:2024-10-31 08:13:30 浏览:584
rust编译参数 发布:2024-10-31 08:11:25 浏览:295