HDU 1385 Minimum Transport Cost

issue敲膩害發表於2020-11-20

很老套的問題了

輸出最小字典序的最短路

那麼記錄前驅的時候 p r e pre pre不是簡單的取 m i n min min

因為是字典序,所以要沿著現在的路徑和以前的路徑倒回去

比較兩條路的字典序才能判斷是否要換

#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
const int maxn = 2e6+10;
int n,m;
struct edge{
	int to,nxt,w;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int w)
{
	d[++cnt] = (edge){ v,head[u],w }, head[u] = cnt;
}
typedef pair<int,int>p;
priority_queue<p,vector<p>,greater<p> >q;
int vis[maxn],dis[maxn],pre[maxn],b[maxn];
char str1[maxn],str2[maxn];
int pos=0;
void dfs(int u, char *str)
{
    if(u==inf) return;
    dfs(pre[u],str);
    str[pos++] = u+'0';
}
bool cmp(int origin, int now)
{
    char str1[maxn], str2[maxn];
    pos=0;
    dfs(origin,str1);    str1[pos] = '\0';
    pos=0;
    dfs(now, str2);
    str2[pos++] = origin+'0';     str2[pos]   = '\0';
    if(strcmp(str1, str2)==1)return true;
    return false;
}
void print(int u,int s)
{
	if( u==s ){	printf("%d",s); return; }
	print( pre[u],s );
	printf("-->%d",u);
}
void dijstra(int s,int t)
{
	for(int i=0;i<=n;i++)	dis[i] = pre[i] = inf, vis[i] = 0;
	q.push( p(0,s) ); dis[s] = 0;
	while( !q.empty() )
	{
		int u = q.top().second; q.pop();
		if( vis[u] )	continue;
		vis[u] = 1;	
		for(int i=head[u];i;i=d[i].nxt )
		{
			int v = d[i].to;
			if( dis[v]>dis[u]+d[i].w+b[v] )
			{
				dis[v] = dis[u]+d[i].w+b[v];
				pre[v] = u;
				q.push( p(dis[v],v) );
			}
			else if( dis[v]==dis[u]+d[i].w+b[v] && cmp(v,u) )
				pre[v] = u;
		}
	}
	printf("From %d to %d :\n",s,t);
	printf("Path: ");
	print(t,s);
	if( s==t )	dis[t] = b[t];
	printf("\nTotal cost : %d\n\n",dis[t]-b[t] );
}
int main()
{
	while( cin >> n && n )
	{
		for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			int w; scanf("%d",&w);
			if( w!=-1 )	add(i,j,w);
		}
		for(int i=1;i<=n;i++)	scanf("%d",&b[i] );
		int s,t;
		while( scanf("%d%d",&s,&t)!=EOF&&s!=-1 )	dijstra(s,t);
		cnt = 1;
		for(int i=1;i<=n;i++)	head[i] = 0;
	}
}

相關文章