图论算法模板整理

最短路系列:

spfa:


#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)
#define Abs(a) ((a)>0?(a):-(a))
#define Mod(a,b) (((a)-1+(b))%(b)+1)
int n,m;
int d[N];
struct 
{
	int v,w,next;
}edge[2*M];
int edgehead[N];
int k;
bool vis[N];
void addedge(int u,int v,int w)
{
	edge[k].next=edgehead[u];
	edge[k].w=w;
	edge[k].v=v;
	edgehead[u]=k++;
}
int spfa(int s)
{
	queue<int> que;
	for(int i=1;i<=n;i++)
		d[i]=inf;
	d[s]=0;
	memset(vis,0,sizeof(vis));
	que.push(s);
	while(!que.empty())
	{
		int u=que.front();
		que.pop();
		vis[u]=false;
		for(int i=edgehead[u];i;i=edge[i].next)
		{
			int v=edge[i].v;
			int w=edge[i].w;
			if(d[v]>d[u]+w)
			{
				d[v]=d[u]+w;
				if(!vis[v])
				{
					que.push(v);
					vis[v]=true;
				}
			}
		}
	}
	return d[n];
}
int main()
{
	scanf("%d%d",&m,&n);
	int u,v,w;
	k=1;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		addedge(u,v,w);
		addedge(v,u,w);
	}
	printf("%d\n",spfa(1));
	return 0;
}

dijstra+head:


int n,m;
int d[N];
struct 
{
	int v,w,next;
}edge[2*M];
int edgehead[N];
int k;
bool vis[N];
void addedge(int u,int v,int w)
{
	edge[k].next=edgehead[u];
	edge[k].w=w;
	edge[k].v=v;
	edgehead[u]=k++;
}
struct cmp
{
	bool operator ()(const int a,const int b)
	{
		return d[a]>d[b];
	}
};
int dijstra(int s)
{
	priority_queue<int,vector<int>,cmp> que;
	for(int i=1;i<=n;i++)
		d[i]=inf;
	d[s]=0;
	memset(vis,0,sizeof(vis));
	que.push(1);
	while(!que.empty())
	{
		int u=que.top();
		que.pop();
		if(vis[u])
			continue;
		vis[u]=true;
		for(int i=edgehead[u];i;i=edge[i].next)
		{
			int v=edge[i].v;
			int w=edge[i].w;
			if(!vis[v]&&d[v]>d[u]+w)
			{
				d[v]=d[u]+w;
				que.push(v);
			}
		}
	}
	return d[n];
}
int main()
{
	scanf("%d%d",&m,&n);
	int u,v,w;
	k=1;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		addedge(u,v,w);
		addedge(v,u,w);
	}
	printf("%d\n",dijstra(1));
	return 0;
}


最大流系列:

dinic:


int n,m;
int mat[N][N];
bool  vis[N];
int level[N];
bool bfs(int s,int t)
{
	memset(vis,0,sizeof(vis));
	memset(level,0,sizeof(level));
	queue<int> que;
	que.push(s);
	vis[s]=true;
	level[s]=0;
	while(!que.empty())
	{
		int now=que.front();
		que.pop();
		if(now==t)
		{
			return true;
		}
		for(int i=0;i<n;i++)
		{
			if(!vis[i]&&mat[now][i])
			{
				vis[i]=true;
				level[i]=level[now]+1;
				que.push(i);
			}
		}
	}
	return false;
}
int dinic(int now,int sum,int t)
{
	if(now==t)
		return sum;
	int os=sum;
	for(int i=0;i<n && sum;i++)
	{
		if(mat[now][i] && level[i]==level[now]+1)
		{
			int ret=dinic(i,Min(sum,mat[now][i]),t);
			mat[now][i]-=ret;
			mat[i][now]+=ret;
			sum-=ret;
		}
	}
	return os-sum;
}
void solve(int s,int t)//s是源点,t是汇点。
{
	int ans=0;
	while(bfs(s,t))
		ans+=dinic(s,inf,t);
	printf("%d\n",ans);
}


二分图最大匹之配匈牙利算法:

int n,m;
bool mat[N][N];
bool vis[N];
int link[N];
bool dfs(int now)
{
	for(int i=1;i<=m;i++)
	{
		if(mat[now][i]&&!vis[i])
		{
			vis[i]=true;
			if(link[i]==0||dfs(link[i]))
			{
				link[i]=now;
				return true;
			}
		}
	}
	return false;
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(link,0,sizeof(link));
		memset(mat,0,sizeof(mat));
		for(int i=1;i<=n;i++)
		{
			int tmp,v;
			scanf("%d",&tmp);
			for(int j=1;j<=tmp;j++)
			{
				scanf("%d",&v);
				mat[i][v]=true;
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			memset(vis,0,sizeof(vis));
			if(dfs(i))
				ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}


最小生成树系列:

prim:

int n,m;
int mat[N][N];
int key[N],pre[N];
bool vis[N];
void prim()
{
	memset(vis,0,sizeof(vis));
	int k;
	for(int i=1;i<=n;i++)
		key[i]=mat[1][i],pre[i]=1;
	vis[1]=true;
	for(int i=1;i<n;i++)
	{
		int min=inf;
		for(int j=1;j<=n;j++)
		{
			if(!vis[j] && min>key[j])
			{
				min=key[j];
				k=j;
			}
		}
		vis[k]=true;
		if(mat[k][pre[k]]!=0)
		{
			printf("%d %d\n",k,pre[k]);
		}
		for(int j=1;j<=n;j++)
		{
			if(!vis[j]&&key[j]>mat[k][j])
				pre[j]=k,key[j]=mat[k][j];
		}
	}
}

kruskal+并查集:

int n,m;
const int N=1005,M=15005;
const int inf=99999999;
int father[N];
struct Edge
{
	int u,v,w;
}edge[M],output[M];
int findfa(int now)
{
	while(father[now]>0)
	{
		now=father[now];
	}
	return now;
}
void Union(int a,int b)
{
	if(father[a]>father[b])
	{
		father[a]+=father[b];
		father[b]=a;
	}
	else
	{
		father[b]+=father[a];
		father[a]=b;
	}
}
bool cmp(const Edge & a,const Edge & b)
{
	return a.w<b.w;
}
void kruskal()
{
	memset(father,-1,sizeof(father));
	sort(edge,edge+m,cmp);
	int count=n-1,k=0,u,v,w,fu,fv;
	for(int i=0;i<m;i++)
	{
		u=edge[i].u;
		v=edge[i].v;
		w=edge[i].w;
		fu=findfa(u);
		fv=findfa(v);
		if(fu!=fv)
		{
			output[k]=edge[i];
			Union(fu,fv);
			k++;
		}
	}
	printf("%d\n%d\n",output[n-2].w,n-1);
	for(int i=0;i<n-1;i++)
		printf("%d %d\n",output[i].u,output[i].v);
}



你可能感兴趣的:(图论算法模板整理)