P2169 正则表达式

在Internet网络中的每台电脑并不是直接一对一连通的,而是某些电脑之间存在单向的网络连接,也就是说存在A到B的连接不一定存在B到A的连接,并且有些连接传输速度很快,有些则很慢,所以不同连接传输所花的时间是有大有小的。另外,如果存在A到B的连接的同时也存在B到A的连接的话,那么A和B实际上处于同一局域网内,可以通过本地传输,这样花费的传输时间为0。

现在小Z告诉你整个网络的构成情况,他希望知道从他的电脑(编号为1),到小X的电脑(编号为n)所需要的最短传输时间。

题意:给你一个带权有向图,如果两个点之间可以互相到达,那么他们之间的边权为\(0\),求从起点\(1\)\(n\)的最短路。

缩点+最短路

缩完点把在同一个强连通分量里的点边权设成\(0\)

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#define N 250000
#define INF 99999999
using namespace std;
struct edge
{
	int to,cost;
};
vector <edge> a[N];
queue <int> q;
int n,m,dfn[N],low[N],co[N],stk[N],top,num,cnt,dis[N],vis[N];
void tarjan(int u)   //tarjan求强连通分量
{
	low[u]=dfn[u]=++cnt;
	stk[++top]=u;
	vector <edge>::iterator it;
	for (it=a[u].begin();it!=a[u].end();it++)
	{
		int v=(*it).to;
		if (!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else
			if (!co[v])
				low[u]=min(low[u],dfn[v]);
	}
	if (low[u]==dfn[u])
	{
		co[u]=++num;       //给强连通分量编号
		while (stk[top]!=u)
			co[stk[top]]=num,top--;
		top--;
	}
}
void spfa()   //单源最短路
{
		for (int i=1;i<=n;i++)
		dis[i]=INF;
	dis[1]=0;
	q.push(1);
	vis[1]=1;
	vector <edge>::iterator it;
	while (!q.empty())
	{
		int u=q.front();q.pop();
		vis[u]=0;
		for (it=a[u].begin();it!=a[u].end();it++)
		{
			int v=(*it).to,w=(*it).cost;
			if (co[u]==co[v])w=0;
			if (dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				if (!vis[v])
					q.push(v),vis[v]=1;
			}
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	int x,y,z;
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		a[x].push_back((edge){y,z});
	}
	for (int i=1;i<=n;i++)
		if (!dfn[i])
			tarjan(i);
	spfa();
	printf("%d",dis[n]);
	return 0;
}

偷懒写的\(spfa\)\(vector\)QAQ

posted @ 2020-06-08 20:39  eee_hoho  阅读(141)  评论(0编辑  收藏  举报