您的位置:首页 > 其它

Codeforces Round #303 (Div. 2) - E. Paths and Trees(最短路)

2015-08-17 14:44 357 查看
题目:

http://codeforces.com/problemset/problem/545/E

题意:

在n个点m条边的无向图中,在保证每个点到s点都是最短距离的情况下, 得到的树边权和最小,输出边权和以及路径编号。

思路:

spfa跑最短路的过程中,当该点到起点的最短路径相同时,选择边权小的路径加入答案的最小生成树中。

AC.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>

using namespace std;
typedef long long ll;
const ll inf = 1e16;
const int maxn = 3e5+5;
int n, m;
int rod[maxn];

int tot, head[maxn];
struct Edge {
int to, next;
ll w;
}edge[maxn*2];
void addedge(int u, int v, ll w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}

ll dis[maxn], val[maxn];
int vis[maxn], pre[maxn], du[maxn];
void spfa(int s)
{
queue<int> que;
memset(pre, 0, sizeof(pre));
memset(vis, 0, sizeof(vis));
memset(du, 0, sizeof(du));
fill(dis, dis+n+1, inf);

que.push(s);
vis[s] = 1;
dis[s] = 0;

while(!que.empty()) {
int u = que.front(); que.pop();
vis[u] = 0;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to, w = edge[i].w;

if(dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
pre[v] = i/2+1;

if(!vis[v]) {
que.push(v);
vis[v] = 1;
}
}
else if(dis[v] == dis[u] + w) {
if(w < val[pre[v]]) {
pre[v] = i/2+1;
if(!vis[v]) {
que.push(v);
vis[v] = 1;
}
}
}
}
}
}
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
int main()
{
//freopen("in", "r", stdin);
while(~scanf("%d%d", &n, &m)) {
init();
for(int i = 1; i <= m; ++i) {
int u, v;
ll w;
scanf("%d%d%I64d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
val[i] = w;
}

int s;
scanf("%d", &s);
spfa(s);

ll ans = 0;
int cnt = 0;
for(int i = 1; i <= n; ++i) {
if(pre[i]) {
ans += val[pre[i]];
rod[cnt++] = pre[i];
}
}

printf("%I64d\n", ans);
for(int i = 0; i < cnt; ++i) {
printf("%d", rod[i]);
if(i != cnt-1) printf(" ");
else printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Codeforces