您的位置:首页 > 其它

HDU 1385 Minimum Transport Cost 【最短路 + 最小字典序路径输出】

2018-01-26 16:42 621 查看
传送门

// 题意: 给定一个矩阵表示点与边的关系, 有向边, 并且每个点有税收, 起点和终点不收税. 然后给出一系列的询问, st 到 ed的最短路是多少, 并且要输出该路径, 特别注意就是如果有同样的答案的最短路, 输出字典序最小的那条.

// 思路: 首先还是最短路, 那么注意几个问题, 一是在结构体中加string name, 不能单纯的以前面那个点来排, 因为有可能小的在前面, 所以我们应该吧前面所选过的全部先存下来, 去总的最小, 而不是前面的那个最小. 其次就是如果有相等距离的, 我们应该比较下它上次取该值的字典序和当前的进行一次比较, 如果更小依旧要进行更新. 具体细节请看代码.

几个坑点 :

1:

6

0 100 100 100 1 1

100 100 100 1 100 100

100 100 100 1 100 100

100 100 100 100 100 100

100 100 1 100 100 100

100 1 100 100 100 100

0 0 0 0 0 0

1 4

-1 -1

ans : 1->5->3->4

2:

3

0 2 4

-1 0 1

-1 -1 0

1 1 1

1 3

1 1

-1 -1

ans: 1 -> 2 -> 3

3: 自己到自己输出 st, 而不是st -> st.

这几个都能过就没有问题了.

AC Code

const int inf = 0x3f3f3f3f; //用这个可以直接mem
const int maxn = 50+5;
int cas=1;
int cnt, head[maxn];
int g[maxn][maxn];
struct node
{
int to, next, w;
string name;
bool operator < (const node& a) const {
if (w != a.w) return w > a.w;
return name > a.name; // 保证总的最小而不单单是前面那个最小.
}
} e[maxn*maxn];

void add(int u, int v,int w) {
e[cnt] = (node){v,head[u],w, ""};
head[u] = cnt++;
}

void init() {
cnt = 0;
memset(head, -1, sizeof(head));
}

bool vis[maxn];
int dis[maxn], a[maxn], pre[maxn];
void dij(int st,int ed)
{
priority_queue<node> q;
Fill(dis,inf); Fill(vis,0); string s[maxn];
dis[st] = 0; string tmp ; tmp += st + '0';
q.push((node){st, 0, 0, tmp});
while (!q.empty()) {
node u = q.top();
q.pop();
if (u.to == ed) break;
if(vis[u.to]) continue;
vis[u.to] = 1;

string tt = u.name;
for (int i = head[u.to]; ~i; i = e[i].next) {
node k = e[i];
int w = dis[u.to] + k.w;
if (k.to != ed) w += a[k.to];
string tmp = (tt += k.to +'0');  // 这个是用来比较相等的情况的.
if (dis[k.to] > w || (dis[k.to] == w && tmp < s[k.to])) {
dis[k.to] = w; s[k.to] = tmp;
pre[k.to] = u.to;
q.push((node){k.to, 0, dis[k.to], s[k.to]});
}
tt = u.name;
}
}
}
int ans[maxn];
void solve() {
int n;
while(~scanf("%d", &n) && n) {
init();
for (int i = 1 ; i <= n ; i ++) {
for (int j = 1 ; j <= n ; j ++) {
scanf("%d", &g[i][j]);
if (g[i][j] != -1 && i != j) {
add(i, j, g[i][j]);
}
}
}
for (int i = 1 ; i <= n ; i ++) scanf("%d", &a[i]);
int st, ed;
while(1) {
scanf("%d%d", &st, &ed);
if (st == -1 && ed == -1) break;
Fill(pre, -1); pre[st] = st;
dij(st, ed); Fill(ans ,0);
printf("From %d to %d :\n", st, ed);
if (st == ed) printf("Path: %d\n", st);
else {
printf("Path: %d-->", st);
int tt = pre[ed]; int k = 0;
while(tt != st) {
ans[++k] = tt;
tt = pre[tt];
}
for (int i = k ; i >= 1 ; i --) {
printf("%d-->", ans[i]);
}
printf("%d\n", ed);
}
printf("Total cost : %d\n\n", dis[ed]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: