您的位置:首页 > 其它

HDU 1535 Invitation Cards (最短路,附SLF优化SPFA)

2014-09-01 20:17 579 查看
题目:

http://acm.hdu.edu.cn/showproblem.php?pid=1535

题意:

有向图,求点1到点2-n的最短距离之和以及点2-n到点1的最短距离之和

方法:

1、跑1为原点的最短路

2、反向建图(把有向图的边反向,(u,v,w)变成(v,u,w)),跑1为原点的最短路

3、将两者距离之和加和即可(注意用 long long ,int会溢出)

void input()
{
scanf("%d%d", &n, &m);
g1.init(n);
g2.init(n);
for (int i = 0; i < m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g1.addse(u, v, w);
g2.addse(v, u, w);
}
}
void solve()
{
g1.spfa(1);
g2.spfa(1);
LL ans = 0;
for (int i = 1; i <= n; i++)
ans += g1.d[i], ans += g2.d[i];
printf("%I64d\n", ans);
}


加SLF优化的SPFA:

设队列队首元素为x,目前元素为v,若d[v]<d[x]则将v插入队列首,否则插入队列尾

/********************************************
*ACM Solutions
*
*@Title:
*@Version: 1.0
*@Time: 2014-xx-xx
*@Solution: http://www.cnblogs.com/xysmlx/p/xxxxxxx.html *
*@Author: xysmlx(Lingxiao Ma)
*@Blog: http://www.cnblogs.com/xysmlx *@EMail: xysmlx@163.com
*
*Copyright (C) 2011-2015 xysmlx(Lingxiao Ma)
********************************************/
// #pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <list>
#include <map>
#include <iterator>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long LL;
#define pb push_back
#define ROUND(x) round(x)
#define FLOOR(x) floor(x)
#define CEIL(x) ceil(x)
const int maxn = 1000010;
const int maxm = 2000010;
const int inf = 0x3f3f3f3f;
const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
const double INF = 1e30;
const double eps = 1e-6;
const int P[4] = {0, 0, -1, 1};
const int Q[4] = {1, -1, 0, 0};
const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};

struct SPFA
{
struct Edge
{
int u, v, w;
int next;
} edge[maxm];
int head[maxn], en;
int n, m;
int d[maxn];
int cnt[maxn];
int mark[maxn];
deque<int> Q;
int pre[maxn];//用于解析路径
void addse(int u, int v, int w)
{
edge[en].u = u;
edge[en].v = v;
edge[en].w = w;
edge[en].next = head[u];
head[u] = en++;
}
void init(int _n)
{
n = _n;
memset(head, -1, sizeof(head));
en = 0;
while (!Q.empty()) Q.pop_back();
}

/*DFS找负环
bool cir[maxn];
void dfs(int u)
{
cir[u]=true;
for(int i=head[u]; i!=-1; i=edge[i].next)
if(!cir[edge[i].v]) dfs(edge[i].v);
}
*/
bool spfa(int s)
{
for (int i = 1; i <= n; ++i) d[i] = inf;
for (int i = 1; i <= n; ++i) pre[i] = i; //用于解析路径
memset(mark, 0, sizeof(mark));
memset(cnt, 0, sizeof(cnt));
d[s] = 0;
Q.push_back(s);
mark[s] = 1;
cnt[s]++;
while (Q.size())
{
int u = Q.front();
Q.pop_front();
mark[u] = 0;
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
int w = edge[i].w;
if (d[u] + w < d[v])
{
pre[v] = u; // 用于解析路径
d[v] = d[u] + w;
if (mark[v] == 0)
{
mark[v] = 1;
if (!Q.empty())
{
if (d[v] > d[Q.front()]) Q.push_back(v);
else Q.push_front(v);
}
else Q.push_back(v);
if (++cnt[v] > n) return false; //有负环,可以用DFS找
}
}
}
}
return true;
}
} g1, g2;

int kase;
int n, m;
void init()
{
kase++;
}
void input()
{
scanf("%d%d", &n, &m);
g1.init(n);
g2.init(n);
for (int i = 0; i < m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g1.addse(u, v, w);
g2.addse(v, u, w);
}
}
void debug()
{
//
}
void solve()
{
g1.spfa(1);
g2.spfa(1);
LL ans = 0;
for (int i = 1; i <= n; i++)
ans += g1.d[i], ans += g2.d[i];
printf("%I64d\n", ans);
}
void output()
{
//
}
int main()
{
// int size = 256 << 20; // 256MB
// char *p = (char *)malloc(size) + size;
// __asm__("movl %0, %%esp\n" :: "r"(p));

// std::ios_base::sync_with_stdio(false);
#ifdef xysmlx
freopen("in.cpp", "r", stdin);
#endif

kase = 0;
int T;
scanf("%d", &T);
while (T--)
{
init();
input();
solve();
output();
}
return 0;
}


HDU 1535
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: