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