G. Lexicographically Minimum Walk

https://codeforces.com/group/5yyKg9gx7m/contest/280318/problem/G
题意:带权有向图,权各不相同,求s到t字典序最小的路径,若长度超过1e6输出过长即可。
思路:权各不相同,所以每次贪心走权最小的并且可以到达t的,因此,先逆边dfs求出每个点是否可达t,然后再从s开始dfs一次,遇到相同结点就是过长,先到达t就输出路径。

#include
using namespace std;
const int maxn=100000+100;
typedef pair<int,int> P;
typedef long long ll;
#define MP(a,b) make_pair(a,b)

int n,m,s,t,vis[maxn],vis2[maxn];
vector<P> G[maxn];
vector<int> G2[maxn],path;

bool cmp(P a,P b){return a.second<b.second;}

void dfs(int v)
{
	vis[v]=1;
	for(int i=0;i<G2[v].size();i++)
	{
		int u=G2[v][i];
		if(!vis[u])dfs(u);
	}
}

void dfs2(int u)
{
	if(vis2[u]){cout<<"TOO LONG";exit(0);}
	vis2[u]=1;
	if(u==t){for(int i=0;i<path.size();i++)printf("%d ",path[i]);exit(0);}
	for(int i=0;i<G[u].size();i++)
	{
		if(vis[G[u][i].first])path.push_back(G[u][i].second),dfs2(G[u][i].first);
	}
}

int main()
{
//	freopen("input.in","r",stdin);
	cin>>n>>m>>s>>t;
	while(m--)
	{
		int u,v,co;
		scanf("%d%d%d",&u,&v,&co);
		G[u].push_back(MP(v,co));
		G2[v].push_back(u);
	}
	for(int i=1;i<=n;i++)sort(G[i].begin(),G[i].end(),cmp);
	dfs(t);
	if(!vis[s]){cout<<"IMPOSSIBLE";exit(0);}
	dfs2(s);
	return 0;
}
 
 
 

你可能感兴趣的:(DFS)