习题:President and Roads(最短路)

题目

传送门

思路

经过边的必然性很容易将其和桥联系起来

考虑如果可能经过一条边,那么这条边一定在最短路上面

可以预处理出这些最短路所构成的图

如果经过某一条边,那么这条边必然在图上是一个桥,因为题目中可能出现重边,所以在tarjan的时候要改一下continue的条件

如果要经过某一条边,那么我们只需要将经过这条边的最短路比原来的最短路小即可

用前向星会好写很多,笔者当时脑子一抽就写了vector

代码

#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<queue>
#include<stack>
#include<map>
using namespace std;
namespace IO
{
	void read(int &x)
	{
		x=0;
		int f=1;
		char c=getchar();
		while('0'>c||c>'9')
		{
			if(f=='-')
				f=-1;
			c=getchar();
		}
		while('0'<=c&&c<='9')
		{
			x=(x<<3)+(x<<1)+c-'0';
			c=getchar();
		}
		x*=f;
	}
	void read(long long &x)
	{
		x=0;
		int f=1;
		char c=getchar();
		while('0'>c||c>'9')
		{
			if(f=='-')
				f=-1;
			c=getchar();
		}
		while('0'<=c&&c<='9')
		{
			x=(x<<3)+(x<<1)+c-'0';
			c=getchar();
		}
		x*=f;
	}
	void write(int x)
	{
		if(x<10)
			putchar(x+'0');
		else
		{
			write(x/10);
			putchar(x%10+'0');
		}
	}
	void write(long long x)
	{
		if(x<10)
			putchar(x+'0');
		else
		{
			write(x/10);
			putchar(x%10+'0');
		}
	}
}
using namespace IO;
struct graph
{
	struct node
	{
		int e;
		long long w;
		friend bool operator < (const node &a,const node &b)
		{
			return a.w>b.w;
		}
	};
	int n,id;
	int dfn[100005],low[100005],bel[100005],cnt,scc;
	bool ins[100005];
	long long dis[100005];
	stack<int> s;
	priority_queue<node> q;
	vector<node> g[100005];
	vector<int> dag[100005];
	map<int,int> f[100005];
	void add_edge(int u,int v,long long w)
	{
		g[u].push_back((node){v,w});
	}
	void dij(int u)
	{
		memset(dis,0x3f,sizeof(dis));
		q.push((node){u,0});
		while(!q.empty())
		{
			node t=q.top();
			q.pop();
			if(t.w>=dis[t.e])
				continue;
			dis[t.e]=t.w;
			for(int i=0;i<g[t.e].size();i++)
			{
				int v=g[t.e][i].e;
				if(dis[v]>t.w+g[t.e][i].w)
					q.push((node){v,t.w+g[t.e][i].w});
			}
		}
	}
	void build()
	{
		for(int i=1;i<=n;i++)
			for(int j=0;j<g[i].size();j++)
				if(dis[i]+g[i][j].w==dis[g[i][j].e])
				{
					dag[i].push_back(g[i][j].e);
					dag[g[i][j].e].push_back(i);
					f[i][dag[i].size()-1]=++id;
					f[g[i][j].e][dag[g[i][j].e].size()-1]=id;
				}
	}
	void tarjan(int u,int fa)
	{
		s.push(u);
		ins[u]=1;
		dfn[u]=low[u]=++cnt;
		for(int i=0;i<dag[u].size();i++)
		{
			int v=dag[u][i];
			if(f[u][i]==fa)
				continue;
			if(dfn[v]==0)
			{
				tarjan(v,f[u][i]);
				low[u]=min(low[u],low[v]);
			}
			else if(ins[v])
				low[u]=min(low[u],dfn[v]);
		}
		if(low[u]==dfn[u])
		{
			int v;
			scc++;
			do
			{
				v=s.top();
				s.pop();
				ins[v]=0;
				bel[v]=scc;
			}while(v!=u);
		}
	}
	void debug()
	{
		for(int i=1;i<=n;i++)
			for(int j=0;j<g[i].size();j++)
				if(dis[i]+g[i][j].w==dis[g[i][j].e])
					cout<<i<<' '<<g[i][j].e<<'\n';
		for(int i=1;i<=n;i++)
			cout<<bel[i]<<' ';
		cout<<'\n';
	}
}g1,g2;
struct edge
{
	int u,v;
	long long w;
}a[100005];
int n,m,s,t;
int main()
{
	read(n);read(m);read(s);read(t);
	g1.n=g2.n=n;
	for(int i=1,u,v;i<=m;i++)
	{
		long long w;
		read(u);read(v);read(w);
		a[i].u=u;a[i].v=v;a[i].w=w;
		g1.add_edge(u,v,w);
		g2.add_edge(v,u,w);
	}
	g1.dij(s);g2.dij(t);
	for(int i=1;i<=m;i++)
		if(g1.dis[a[i].u]+a[i].w+g2.dis[a[i].v]==g1.dis[t])
		{
			g1.dag[a[i].u].push_back(a[i].v);
			g1.dag[a[i].v].push_back(a[i].u);
			g1.f[a[i].u][g1.dag[a[i].u].size()-1]=++g1.id;
			g1.f[a[i].v][g1.dag[a[i].v].size()-1]=g1.id;
		}
	for(int i=1;i<=n;i++)
		if(g1.dfn[i]==0)
			g1.tarjan(i,0);
	for(int i=1;i<=m;i++)
	{
		if(g1.bel[a[i].u]!=g1.bel[a[i].v]&&g1.dis[a[i].u]+a[i].w+g2.dis[a[i].v]==g1.dis[t])
			puts("YES");
		else if(g1.dis[t]-1-g1.dis[a[i].u]-g2.dis[a[i].v]<=0)
			puts("NO");
		else
		{
			printf("CAN ");
			write(a[i].w-(g1.dis[t]-1-g1.dis[a[i].u]-g2.dis[a[i].v]));
			putchar('\n');
		}
		
	}
	return 0;
}
posted @ 2020-08-23 18:50  loney_s  阅读(122)  评论(0)    收藏  举报