标程_图论

标程_图论

图的遍历

深搜+邻接矩阵

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,sum;
bool a[110][110],b[110];
void DFS(int dep)
{
	int i;
	b[dep]=0;
	sum++;
	for(i=1;i<=n;i++)
		if(b[i]&&a[dep][i])
			DFS(i);
	return;
}
int main()
{
	int x,y,ans=0,i;
	memset(a,false,sizeof(a));
	memset(b,true,sizeof(b));
	scanf("%d",&n);
	for(scanf("%d%d",&x,&y);x||y;a[x][y]=a[y][x]=1,scanf("%d%d",&x,&y));
	for(i=1;i<=n;i++)
		if(b[i])
		{
			sum=0;
			DFS(i);
			ans=max(ans,sum);
		}
	printf("%d",ans);
	return 0;
}

深搜+邻接表

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct jgt
{
	int x,y,nxt;
}a[10010];
int n,sum,tot=0,head[110];
bool b[110];
void add(int x,int y)
{
	tot++;
	a[tot].x=x;
	a[tot].y=y;
	a[tot].nxt=head[x];
	head[x]=tot;
	return;
}
void DFS(int dep)
{
	int i;
	b[dep]=0;
	sum++;
	for(i=head[dep];i;i=a[i].nxt)
		if(b[a[i].y])
			DFS(a[i].y);
	return;
}
int main()
{
	int x,y,ans=0,i;
	memset(a,false,sizeof(a));
	memset(b,true,sizeof(b));
	memset(head,0,sizeof(head));
	scanf("%d",&n);
	for(scanf("%d%d",&x,&y);x||y;add(x,y),add(y,x),scanf("%d%d",&x,&y));
	for(i=1;i<=n;i++)
		if(b[i])
		{
			sum=0;
			DFS(i);
			ans=max(ans,sum);
		}
	printf("%d",ans);
	return 0;
}

广搜+邻接矩阵

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,sum;
bool a[110][110],b[110];
int c[10010];
void BFS(int dep)
{
	int l,r,i;
	b[dep]=0;
	c[0]=dep;
	for(l=r=0;l<=r;l++)
	{
		for(i=1;i<=n;i++)
		{
			if(a[c[l]][i]&&b[i])
			{
				b[i]=0;
				c[++r]=i;
			}
		}
	}
	sum=r+1;
	return;
}
int main()
{
	int x,y,ans=0,i;
	memset(a,false,sizeof(a));
	memset(b,true,sizeof(b));
	scanf("%d",&n);
	for(scanf("%d%d",&x,&y);x||y;a[x][y]=a[y][x]=1,scanf("%d%d",&x,&y));
	for(i=1;i<=n;i++)
		if(b[i])
		{
			sum=0;
			BFS(i);
			ans=max(ans,sum);
		}
	printf("%d",ans);
	return 0;
}

广搜+邻接表

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct jgt
{
	int x,y,nxt;
}a[10010];
int n,sum,tot=0,head[110],c[10010];
bool b[110];
void add(int x,int y)
{
	tot++;
	a[tot].x=x;
	a[tot].y=y;
	a[tot].nxt=head[x];
	head[x]=tot;
	return;
}
void BFS(int dep)
{
	int l,r,i;
	b[dep]=0;
	c[0]=dep;
	for(l=r=0;l<=r;l++)
	{
		for(i=head[c[l]];i;i=a[i].nxt)
		{
			if(b[a[i].y])
			{
				b[a[i].y]=0;
				c[++r]=a[i].y;
			}
		}
	}
	sum=r+1;
	return;
}
int main()
{
	int x,y,ans=0,i;
	memset(a,false,sizeof(a));
	memset(b,true,sizeof(b));
	memset(head,0,sizeof(head));
	scanf("%d",&n);
	for(scanf("%d%d",&x,&y);x||y;add(x,y),add(y,x),scanf("%d%d",&x,&y));
	for(i=1;i<=n;i++)
		if(b[i])
		{
			sum=0;
			BFS(i);
			ans=max(ans,sum);
		}
	printf("%d",ans);
	return 0;
}

广搜+STL

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct jgt
{
	int x,y,nxt;
}a[10010];
int n,sum,tot=0,head[110];
bool b[110];
queue<int>c;
void add(int x,int y)
{
	tot++;
	a[tot].x=x;
	a[tot].y=y;
	a[tot].nxt=head[x];
	head[x]=tot;
	return;
}
void BFS(int dep)
{
	int i;
	b[dep]=0;
	for(c.push(dep);!c.empty();c.pop())
	{
		for(i=head[c.front()];i;i=a[i].nxt)
		{
			if(b[a[i].y])
			{
				b[a[i].y]=0;
				c.push(a[i].y);
				sum++;
			}
		}
	}
	return;
}
int main()
{
	int x,y,ans=0,i;
	memset(a,false,sizeof(a));
	memset(b,true,sizeof(b));
	memset(head,0,sizeof(head));
	scanf("%d",&n);
	for(scanf("%d%d",&x,&y);x||y;add(x,y),add(y,x),scanf("%d%d",&x,&y));
	for(i=1;i<=n;i++)
		if(b[i])
		{
			sum=1;
			BFS(i);
			ans=max(ans,sum);
		}
	printf("%d",ans);
	return 0;
}

最小生成树

prim+邻接矩阵

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int n,a[110][110],ans=0,tot=0,mn[110];
bool d[110];
void input()
{
	int i,j;
	memset(mn,100,sizeof(mn));
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	return;
}
void prim()
{
	int i,j,w;
	memset(d,true,sizeof(d));
	mn[1]=0;
	for(i=1;i<n;i++)
	{
		for(w=0,j=1;j<=n;j++)
			if(d[j]&&mn[j]<mn[w])
				w=j;
		d[w]=0;
		for(j=1;j<=n;j++)
			if(d[j]&&a[w][j]<mn[j])
				mn[j]=a[w][j];
	}
	for(i=1;i<=n;i++)
		ans+=mn[i];
	return;
}
int main()
{
	input();
	prim();
	printf("%d",ans);
	return 0;
}

prim+邻接表

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int n,a[110][110],ans=0,tot=0,mn[110],head[110];
bool d[110];
struct jgt
{
	int x,y,w,nst;
}f[10010];
void input()
{
	int i,j;
	memset(mn,100,sizeof(mn));
	memset(head,0,sizeof(head));
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
		{
			scanf("%d",&a[i][j]);
			if(a[i][j])	
			{
				tot++;
				f[tot].x=i;
				f[tot].y=j;
				f[tot].w=a[i][j];
				f[tot].nst=head[i];
				head[i]=tot;
			}
		}
	return;
}
void prim()
{
	int i,j,w;
	memset(d,true,sizeof(d));
	mn[1]=0;
	for(i=1;i<n;i++)
	{
		for(w=0,j=1;j<=n;j++)
			if(d[j]&&mn[j]<mn[w])
				w=j;
		d[w]=0;
		for(j=head[w];j;j=f[j].nst)
			if(d[f[j].y]&&a[w][f[j].y]<mn[f[j].y])
				mn[f[j].y]=a[w][f[j].y];
	}
	for(i=1;i<=n;i++)
		ans+=mn[i];
	return;
}
int main()
{
	input();
	prim();
	printf("%d",ans);
	return 0;
}

kruskal

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int n,a[110][110],ans=0,tot=0,b[110];
bool d[110];
struct jgt
{
	int x,y,w;
}f[10010];
int bcj(int x)
{
	if(b[x]==x)
		return x;
	b[x]=bcj(b[x]);
	return b[x];
}
bool cmp(jgt t1,jgt t2)
{
	return t1.w<t2.w;
}
void input()
{
	int i,j;
	scanf("%d",&n);
	for(i=1;i<=n;b[i]=i,i++)
		for(j=1;j<=n;j++)
		{
			scanf("%d",&a[i][j]);
			if(i<j)
			{
				f[tot].x=i;
				f[tot].y=j;
				f[tot++].w=a[i][j];
			}
		}
	return;
}
void kruskal()
{
	int i,x;
	sort(f,f+tot,cmp);
	for(i=0;n;i++)
	{
		if(bcj(f[i].x)!=bcj(f[i].y))
		{
			n--;
			ans+=f[i].w;
			b[bcj(f[i].x)]=bcj(f[i].y);
		}
	}
	return;
}
int main()
{
	input();
	kruskal();
	printf("%d",ans);
	return 0;
}

最短路

floyd

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,dx,dy;
double a[110][110],x[110],y[110];
void input()
{
	int i,j;
	memset(a,0x7f7f7f,sizeof(a));
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%lf%lf",&x[i],&y[i]);//保存坐标 
		a[i][i]=0;
	}
	scanf("%d",&m);
	for(i=0;i<m;i++)
	{
		scanf("%d%d",&dx,&dy);
		a[dx][dy]=a[dy][dx]=sqrt((x[dx]-x[dy])*(x[dx]-x[dy])+(y[dx]-y[dy])*(y[dx]-y[dy]));//计算距离
	}
	scanf("%d%d",&dx,&dy);
	return;
}
void floyed()//计算最短路 
{
	int i,j,k,w;
	for(k=1;k<=n;k++)
		for(i=1;i<n;i++)
			for(j=i+1;j<=n;j++)
				if(a[i][j]>a[i][k]+a[k][j])
					a[i][j]=a[j][i]=a[i][k]+a[k][j];
	return;
}
int main()
{
	input();
	floyed();
	printf("%.2lf",a[dx][dy]);
	return 0;
}

dijkstra(n^2)

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int e[3010][3010],dis[3010],head[3010],tot;
bool d[3010];
void DIJ(int n)
{
	int i,j,mn,w;
	for(i=1;i<=n;i++)
	{
		e[i][i]=0;
		dis[i]=e[1][i];
	}
	dis[1]=0;
	d[1]=1;
	for(i=1;i<n;i++)
	{
		mn=10000000;
		for(j=2;j<=n;j++)
		{
			if(!d[j]&&dis[j]<mn)
			{
				w=j;
				mn=dis[j];
			}
		}
		d[w]=1;
		for(j=2;j<=n;j++)
		{
			if(!d[j]&&dis[w]+e[w][j]<dis[j])
				dis[j]=dis[w]+e[w][j];
		}
	}
	return;
}
int main()
{
	int n,m,i,u,v,w;
	memset(e,1,sizeof(e));
	scanf("%d%d",&n,&m);
	tot=0;
	for(i=0;i<m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		e[u][v]=e[v][u]=w;
	}
	DIJ(n);
	for(i=1;i<=n;i++)
		printf("%d %d\n",i,dis[i]);
	return 0;
}

dijkstra堆优化

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct jgt
{
	int w,s;
};
struct NOTE
{
	int x,y,nxt,s;
}f[3010];
bool operator < (const jgt &a,const jgt &b)
{
	return a.s>b.s;
}
priority_queue<jgt>q;
int e[3010][3010],dis[3010],head[3010],tot;
bool d[3010];
void DIJ(int n)
{
	jgt tem,temp;
	int i,j,mn,w,v;
	for(i=1;i<=n;i++)
	{
		e[i][i]=0;
		dis[i]=e[1][i];
	}
	for(i=head[1];i>0;i=f[i].nxt)
	{
		tem.w=f[i].y;
		tem.s=dis[f[i].y];
		q.push(tem);
	}
	for(dis[1]=0,d[1]=1;!q.empty();)
	{
		tem=q.top();
		q.pop();
		d[tem.w]=1;
		for(j=head[tem.w];j>0;j=f[j].nxt)
		{
			if(!d[f[j].y]&&tem.s+e[tem.w][f[j].y]<dis[f[j].y])
			{
				dis[f[j].y]=tem.s+e[tem.w][f[j].y];
				temp.w=f[j].y;
				temp.s=dis[f[j].y];
				q.push(temp);
			}
		}
	}
	return;
}
void add(int u,int v,int w)
{
	f[++tot].x=u;
	f[tot].y=v;
	f[tot].s=w;
	f[tot].nxt=head[u];
	head[u]=tot;
	return;
}
int main()
{
	int n,m,i,u,v,w;
	memset(e,1,sizeof(e));
	scanf("%d%d",&n,&m);
	tot=0;
	for(i=0;i<m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		add(v,u,w);
		e[u][v]=e[v][u]=w;
	}
	DIJ(n);
	for(i=1;i<=n;i++)
		printf("%d %d\n",i,dis[i]);
	return 0;
}

ford

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,dx,dy;
double x[110],y[110],dis[110];
struct jgt
{
	int x,y;
	double s;
}b[10000]; 
void input()
{
	int i,j;
	scanf("%d",&n);
	dis[0]=100000000;
	for(i=1;i<=n;i++)
	{
		scanf("%lf%lf",&x[i],&y[i]);//保存坐标
		dis[i]=100000000;
	}
	scanf("%d",&m);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&b[i].x,&b[i].y);
		b[i].s=sqrt((x[b[i].x]-x[b[i].y])*(x[b[i].x]-x[b[i].y])+(y[b[i].x]-y[b[i].y])*(y[b[i].x]-y[b[i].y]));//计算距离
	}
	scanf("%d%d",&dx,&dy);
	return;
}
void ford()//计算最短路 
{
	int i,j,k,w;
	bool y=1;
	dis[dx]=0;
	for(i=1;y&&i<n;i++)
	{
		y=0;
		for(j=1;j<=m;j++)//扫描每一条边 
		{
			if(dis[b[j].x]+b[j].s<dis[b[j].y])dis[b[j].y]=dis[b[j].x]+b[j].s,y=1;//松弛 
			if(dis[b[j].y]+b[j].s<dis[b[j].x])dis[b[j].x]=dis[b[j].y]+b[j].s,y=1;
		}	
	}
	return;
}
int main()
{
	input();
	ford();
	printf("%.2lf",dis[dy]);
	return 0;
}

spfa_bfs

#include<iostream>
#include<cstdio>
#include<cstring> 
#include<queue>
using namespace std;
bool d[300010];
int n,m,dis[300010],head[300010],tot=0,a[300010];
struct jgt
{
	int x,y,nxt,s;
}f[5000001];
queue<int> q;
void add(int x,int y)//建边 
{
	f[++tot].x=x;
	f[tot].y=y;
	f[tot].s=0;
	f[tot].nxt=head[x];
	head[x]=tot;
	return;
}
void input()
{
	int i,x,y,z;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y);
		add(x+n,y+n);
		add(x+n+n,y+n+n);
		if(z==2)
		{
			add(y,x);
			add(y+n,x+n);
			add(y+n+n,x+n+n);
		}
	}
	for(i=1;i<=n;i++)
	{
		f[++tot].x=i;
		f[tot].y=i+n;
		f[tot].s=-a[i];
		f[tot].nxt=head[i];
		head[i]=tot;
		
		f[++tot].x=i+n;
		f[tot].y=i+n+n;
		f[tot].s=a[i];
		f[tot].nxt=head[i+n];
		head[i+n]=tot;
	}
	return;
}
void SPFA()
{
	int l,r,i;
	memset(d,0,sizeof(d));
	memset(dis,-0x7f7f,sizeof(dis));
	dis[1]=0;
	for(q.push(1),d[1]=1;!q.empty();q.pop())//队列优化 
	{
		for(i=head[q.front()];i;i=f[i].nxt)
			if(dis[f[i].y]<dis[q.front()]+f[i].s)//松弛 
			{
				dis[f[i].y]=dis[q.front()]+f[i].s;
				if(!d[f[i].y])
				{
					q.push(f[i].y);//加入队列 
					d[f[i].y]=1;
				}
			}
		d[q.front()]=0;//退出队列 
	}
	return;
}
int main()
{
	input();
	SPFA();
	printf("%d",dis[3*n]);
	return 0;
}

spfa_dfs

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct jgt
{
	int w,s;
};
struct NOTE
{
	int x,y,nxt,s;
}f[3010];
int e[3010][3010],dis[3010],head[3010],tot;
bool d[3010];
void add(int u,int v,int w)
{
	f[++tot].x=u;
	f[tot].y=v;
	f[tot].s=w;
	f[tot].nxt=head[u];
	head[u]=tot;
	return;
}
bool SPFA(int s)
{
	int i;
	if(d[s])
		return 1;
	d[s]=1;
	for(i=head[s];i>0;i=f[i].nxt)
		if (dis[s]+e[s][f[i].y]<dis[f[i].y])
		{
			dis[f[i].y]=dis[s]+e[s][f[i].y];
			if (SPFA(f[i].y))
				return 1;
		}
	d[s]=0;
	return 0;
}
int main()
{
	int n,m,i,u,v,w;
	memset(e,1,sizeof(e));
	memset(d,0,sizeof(d));
	memset(dis,1,sizeof(dis));
	scanf("%d%d",&n,&m);
	tot=0;
	for(i=0;i<m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		add(v,u,w);
		e[u][v]=e[v][u]=w;
	}
	dis[1]=0;
	if (SPFA(1))
		printf("-1");
	else
		for(i=1;i<=n;i++)
			printf("%d %d\n",i,dis[i]);
	return 0;
}

最小环

/*  最小环就是指在一张图中找出一个环,使得这个环上的各条边的权值之和最小。在Floyed的同时,可以顺便算出最小环。
  记两点间的最短路为dis[i][j],g[i][j]为边<i,j>的权值。*/
for(k=1;k<=n;k++)
{   
	for(i=1;i<=k-1;i++)
		for(j=i+1;j<=k-1;j++)
			answer=min(answer,dis[i][j]+g[j][k]+g[k][i]);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
/* answer即为这张图的最小环。
  一个环中的最大结点为k(编号最大),与它相连的两个点为i,j,这个环的最短长度为g[i][k]+g[k][j]+(i到j的路径中,所有结点编号都小于k的最短路径长度)。
  根据Floyed的原理,在最外层循环做了k-1次之后,dis[i][j]则代表了i到j的路径中,所有结点编号都小于k的最短路径。
  综上所述,该算法一定能找到图中最小环。*/

有向图的强连通分量Kosaraju

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,c[1010],lenc=0;
bool a[210][210],b[210],f[210][210];
void DFS(int dep)
{
	int i;
	b[dep]=0;
	for(i=1;i<=n;i++)
		if(b[i]&&a[dep][i])
		{
			DFS(i);	
			c[++lenc]=i;
		}
	return;
}
void dfs(int dep)
{
	int i;
	b[dep]=0;
	for(i=1;i<=n;i++)
		if(b[i]&&f[dep][i])
			dfs(i);
	return;
}
int main()
{
	int x,j,ans=0,i;
	memset(a,false,sizeof(a));
	memset(b,true,sizeof(b));
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		for(scanf("%d",&x);x;a[i][x]=1,scanf("%d",&x));
	for(i=1;i<=n;i++)
		if(b[i])
			DFS(i),c[++lenc]=i,ans++;
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			if(a[i][j])
				f[j][i]=1;
	memset(b,true,sizeof(b));
	for(i=n;i>=1;i--)
		if(b[c[i]])
			dfs(i),ans++;
	printf("%d",ans);
	return 0;
}

拓扑排序

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int ans[100010],sum=0,tot=0,n,m,head[100010],ins[100010];
queue<int> q;
struct jgt
{
	int x,y,nxt;
}f[200010];
void input()
{
	int i;
	memset(ins,0,sizeof(ins));
	memset(ans,0,sizeof(ans));
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)
	{
		tot++;
		scanf("%d%d",&f[tot].y,&f[tot].x);
		f[tot].nxt=head[f[tot].x];
		head[f[tot].x]=tot;
		ins[f[tot].y]++;
	}
	return;
}
void topsort()
{
	int i;
	for(i=1;i<=n;i++)
		if(!ins[i])
			q.push(i);
	for(;!q.empty();q.pop(),sum++)
	{
		for(i=head[q.front()];i;i=f[i].nxt)//更新入度 
		{
			ins[f[i].y]--;
			if(!ins[f[i].y])//当能够到达这个点的所有点都遍历过后将这个点加入队列
			{
				ans[f[i].y]=ans[q.front()]+1;
				q.push(f[i].y);
			}
		}
	}
	return;
}
void output()
{
	int i,answer=n*100;
	if(sum<n)//循环依赖 
	{
		printf("-1");
		return;
	}
	for(i=1;i<=n;i++)
		answer+=ans[i];
	printf("%d",answer);
	return;
}
int main()
{
	input();
	topsort();
	output();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值