lightoj 1281 - New Traffic System (有限制最短路)
2013-11-26 21:55
369 查看
题意 : 给你一张有向图, 然后在给你k条新的路和一个d,问你在建立不超过d条新路条件下节点0 到节点n - 1 的最短路。
思路 : 这道题目可以转换成有限制的最短路来做的,只要把新边认为w = 1,而旧边就是w = 0,最后w总和不超过 d后就是裸裸的有限制最短路,至于有限制的最短路可以用A* 优化做的,评估函数 是f(x) = g(x) + h(x) 其中g(x)表示的是当前搜索到的满足条件的路径长度,而h(x)表示 x 到节点n - 1的最短路径用Dijkstra建立反向边预处理出来,评估函数满足评估值小于等于实际值这一条件。
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 83178122;
const int maxn = 100005;
struct AS{
int g, h, x, num;
AS(){}
AS(int a, int b, int c, int d) : g(a), h(b), x(c), num(d){}
bool operator < (const AS &cmp)const {
return g + h > cmp.g + cmp.h;
}
};
struct Dist{
int d, x;
Dist(){}
Dist(int a, int b) : d(a), x(b){}
bool operator < (const Dist &cmp)const {
return d > cmp.d;
}
};
struct Edge{
int to, c, w, next;
}edge[2][maxn<<1];
int head[2][maxn], E[2];
int n, m, k, Lim;
int vis[maxn], d[maxn];
void init(){
E[0] = E[1] = 0;
memset(head, -1, sizeof(head));
}
void add_edge(int op, int u, int to, int c, int w){
edge[op][E[op]].to = to; edge[op][E[op]].w = w;
edge[op][E[op]].c = c; edge[op][E[op]].next = head[op][u];
head[op][u] = E[op]++;
}
void Dijkstra(){
fill(d, d+n, INF); d[n-1] = 0;
memset(vis, 0, sizeof(vis));
priority_queue<Dist> q;
q.push(Dist(d[n-1], n-1));
while (!q.empty()){
Dist tmp = q.top(); q.pop();
int u = tmp.x;
if (vis[u])continue;
vis[u] = 1;
for (int i = head[1][u]; i != -1; i = edge[1][i].next){
int to = edge[1][i].to, c = edge[1][i].c;
if (d[to] > d[u] + c){
d[to] = d[u] + c;
q.push(Dist(d[to], to));
}
}
}
return ;
}
int A_star(){
Dijkstra();
priority_queue<AS> q;
q.push(AS(0, d[0], 0, 0));
int ret = INF;
while (!q.empty()){
AS tmp = q.top(); q.pop();
int u = tmp.x;
if (tmp.num > Lim)continue;
if (u == n - 1)return tmp.g;
for (int i = head[0][u]; i != -1; i = edge[0][i].next){
int to = edge[0][i].to, c = edge[0][i].c, w = edge[0][i].w;
q.push(AS(tmp.g+c, d[to], to, tmp.num+w));
}
}
return ret;
}
int main(){
int T;
scanf("%d", &T);
for (int cas = 1; cas<= T; cas++){
scanf("%d%d%d%d", &n, &m, &k, &Lim);
init();
for (int i = 1; i <= m; i++){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add_edge(0, a, b, c, 0);
add_edge(1, b, a, c, 0);
}
for (int i = 1; i <= k; i++){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add_edge(0, a, b, c, 1);
add_edge(1, b, a, c, 1);
}
int ret = A_star();
if (ret >= INF)printf("Case %d: Impossible\n", cas);
else printf("Case %d: %d\n", cas, ret);
}
return 0;
}
思路 : 这道题目可以转换成有限制的最短路来做的,只要把新边认为w = 1,而旧边就是w = 0,最后w总和不超过 d后就是裸裸的有限制最短路,至于有限制的最短路可以用A* 优化做的,评估函数 是f(x) = g(x) + h(x) 其中g(x)表示的是当前搜索到的满足条件的路径长度,而h(x)表示 x 到节点n - 1的最短路径用Dijkstra建立反向边预处理出来,评估函数满足评估值小于等于实际值这一条件。
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 83178122;
const int maxn = 100005;
struct AS{
int g, h, x, num;
AS(){}
AS(int a, int b, int c, int d) : g(a), h(b), x(c), num(d){}
bool operator < (const AS &cmp)const {
return g + h > cmp.g + cmp.h;
}
};
struct Dist{
int d, x;
Dist(){}
Dist(int a, int b) : d(a), x(b){}
bool operator < (const Dist &cmp)const {
return d > cmp.d;
}
};
struct Edge{
int to, c, w, next;
}edge[2][maxn<<1];
int head[2][maxn], E[2];
int n, m, k, Lim;
int vis[maxn], d[maxn];
void init(){
E[0] = E[1] = 0;
memset(head, -1, sizeof(head));
}
void add_edge(int op, int u, int to, int c, int w){
edge[op][E[op]].to = to; edge[op][E[op]].w = w;
edge[op][E[op]].c = c; edge[op][E[op]].next = head[op][u];
head[op][u] = E[op]++;
}
void Dijkstra(){
fill(d, d+n, INF); d[n-1] = 0;
memset(vis, 0, sizeof(vis));
priority_queue<Dist> q;
q.push(Dist(d[n-1], n-1));
while (!q.empty()){
Dist tmp = q.top(); q.pop();
int u = tmp.x;
if (vis[u])continue;
vis[u] = 1;
for (int i = head[1][u]; i != -1; i = edge[1][i].next){
int to = edge[1][i].to, c = edge[1][i].c;
if (d[to] > d[u] + c){
d[to] = d[u] + c;
q.push(Dist(d[to], to));
}
}
}
return ;
}
int A_star(){
Dijkstra();
priority_queue<AS> q;
q.push(AS(0, d[0], 0, 0));
int ret = INF;
while (!q.empty()){
AS tmp = q.top(); q.pop();
int u = tmp.x;
if (tmp.num > Lim)continue;
if (u == n - 1)return tmp.g;
for (int i = head[0][u]; i != -1; i = edge[0][i].next){
int to = edge[0][i].to, c = edge[0][i].c, w = edge[0][i].w;
q.push(AS(tmp.g+c, d[to], to, tmp.num+w));
}
}
return ret;
}
int main(){
int T;
scanf("%d", &T);
for (int cas = 1; cas<= T; cas++){
scanf("%d%d%d%d", &n, &m, &k, &Lim);
init();
for (int i = 1; i <= m; i++){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add_edge(0, a, b, c, 0);
add_edge(1, b, a, c, 0);
}
for (int i = 1; i <= k; i++){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add_edge(0, a, b, c, 1);
add_edge(1, b, a, c, 1);
}
int ret = A_star();
if (ret >= INF)printf("Case %d: Impossible\n", cas);
else printf("Case %d: %d\n", cas, ret);
}
return 0;
}
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- Dijkstra和floyd——求单源点最短路径
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- zoj3549 快速幂
- NWERC2010 NKOJ2178 Stock Prices
- 2011ACM福州网络预选赛B题 HDU4062 Abalone
- Codeforces Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- POJ挑战赛3(POJ Challenge Round 3)题解
- ACM常用算法
- 2013 Multi-University Training Contest 1
- ACM/ICPC需要掌握的知识[转载]
- 北大—1006——Biorhythms
- ZOJ Problem Set - 1711 解题报告