H. Delivery Route 2019 ICPC现场赛 并查集+dijstra

https://nanti.jisuanke.com/t/42388

尝试写了一下spfa没加优化跑不过去,据说加了优化能过?

艹这题也巨水去年没时间写了

由于它说了如果存在单向边从u->v,那么一定无法从v->u,而由于只有单向边有负数,所以对于每一个双向边连起来的连通块内部,是不存在单向边的,那么单向边总是从一个连通块连向另一个连通块,于是就可以按照单向边来拓扑排序

先把当前rudu为0的连通块拿出来用双向边跑一遍dij,然后用单向边去更新别的连通块中的点的最小dis,接着拓扑排序一个新的连通块继续如此操作

有个小细节找了一晚上错误,由于单向边u->v是可能<0的,必须要dis[u]<inf也就是可走到的才能取更新dis[v]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=1e5+10;
const int inf=1e9;

int n,xm,ym,st;
int dis[maxl],f[maxl],du[maxl];
struct ed
{
	int v,l;
};
vector<ed> ex[maxl],ey[maxl];
vector<int> b[maxl];
bool in[maxl];
queue<int> tq;
typedef pair<int,int> p;
priority_queue<p,vector<p>,greater<p>> q;

inline int find(int x)
{
	if(f[x]!=x)
		f[x]=find(f[x]);
	return f[x];
}

inline void prework()
{
	scanf("%d%d%d%d",&n,&xm,&ym,&st);
	for(int i=1;i<=n;i++)
		f[i]=i;
	int u,v,c,x,y;
	for(int i=1;i<=xm;i++)
	{
		scanf("%d%d%d",&u,&v,&c);
		ex[u].push_back(ed{v,c});
		ex[v].push_back(ed{u,c});
		x=find(u);y=find(v);
		f[y]=x;
	}
	for(int i=1;i<=n;i++)
		f[i]=find(i);
	for(int i=1;i<=ym;i++)
	{
		scanf("%d%d%d",&u,&v,&c);
		ey[u].push_back(ed{v,c});
		du[f[v]]++;
	}
}

inline void solv(int id)
{
	while(q.size()) q.pop();
	for(int i:b[id])
	if(dis[i]<inf) 
		q.push({dis[i],i});
	int u;p d;
	while(!q.empty())
	{
		d=q.top();q.pop();
		u=d.second;
		if(d.first!=dis[u])
			continue;
		for(ed ee:ex[u])
		if(dis[ee.v]>dis[u]+ee.l)
		{
			dis[ee.v]=dis[u]+ee.l;
			q.push({dis[ee.v],ee.v});
		}		
	}
	for(int u:b[id])
		for(ed ee:ey[u])
		{
			if(dis[ee.v]>dis[u]+ee.l && dis[u]<inf)
				dis[ee.v]=dis[u]+ee.l;
			du[f[ee.v]]--;
			if(!du[f[ee.v]])
				tq.push(f[ee.v]);
		}
}

inline void mainwork()
{
	for(int i=1;i<=n;i++)
	if(f[i]==i)
	{
		if(du[i]==0)
			tq.push(i);
	}
	for(int i=1;i<=n;i++)
		dis[i]=inf,b[f[i]].push_back(i);
	dis[st]=0;
	while(!tq.empty())
	{
		int u=tq.front();
		tq.pop();
		solv(u);
	}
}

inline void print()
{
	for(int i=1;i<=n;i++)
	if(dis[i]==inf)
		puts("NO PATH");
	else
		printf("%d\n",dis[i]);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/109234346
今日推荐