[Dijkstra] POJ 2253 Frogger | POJ 1797 Heavy Transportation | POJ 3268 Silver Cow Party
POJ 2253 Frogger | POJ 1797 Heavy Transportation | POJ 3268 Silver Cow Party
Dijkstra使用链式前向星实现的G=(V,E)
https://malash.me/200910/linked-forward-star/#comment-25291
由于MAXN上限太大开不了邻接矩阵,又由于卡时间用vector会TLE。
typedef long long LL;
typedef pair<LL,int> Pair;
const int MAX_P = 1000003;
const int INF = 0x3fffffff;
int P;// number of stops including CCS
int Q;// the number of bus lines
/* MLE: 1e12
* int G[MAX_P][MAX_P];// 1-indexed
*/
/* TLE: >8000ms
* vector<vector<Pair>>
* vector<Pair> GS[MAX_P];
* vector<Pair> GD[MAX_P];
* AC: 2188ms
*/
int dis[MAX_P];
int vis[MAX_P];
/*-----数据结构------*/
int head[MAX_P]; //记录以索引i为源点的边的链表的首条边在edge数组中的地址
int rhead[MAX_P];
struct Edge{
int dst;
int w;
int next;
}edge[MAX_P*2]; // 双向Dijkstra中head和rhead共用cnt,若edge开为MAX_P会越界
/*-------add--------*/
int cnt=1;
void add(int head[],int S,int D,int w){
edge[cnt].dst = D;
edge[cnt].w = w;
edge[cnt].next = head[S];
head[S] = cnt++;
/* 不能用++cnt, 只能用cnt++
* 因为数组edge索引和head维护的当前链表头对应的边在edge数组
* 且head==0标志到达链表尾
*/
}
/*------------------*/
void dijkstra(int head[]){
dis[1] = 0;
priority_queue<Pair,vector<Pair>,greater<Pair>> Q;// min-heap
Q.push(Pair(dis[1],1));
while(!Q.empty()){
Pair p = Q.top();
Q.pop();
int cur = p.second;
if(vis[cur]) continue;
vis[cur] = 1;
for(int i=head[cur];i!=0;i=edge[i].next){
int nxt = edge[i].dst;
if(vis[nxt]) continue;
int prc =edge[i].w;
if(dis[cur] + prc < dis[nxt]){
dis[nxt] = dis[cur] + prc;
Q.push(Pair(dis[nxt],nxt));
}
}
}
}
int main(){
int N;
scanf("%d",&N);
for(int n=0;n<N;n++){
fill(head,head+MAX_P,0);
fill(rhead,rhead+MAX_P,0);
cnt = 1;
scanf("%d %d",&P,&Q);
int S,D,price;
for(int q=0;q<Q;q++){
scanf("%d %d %d",&S,&D,&price);
add(head,S,D,price);
add(rhead,D,S,price);
}
LL ans=0;
fill(dis,dis+MAX_P,INF);
fill(vis,vis+MAX_P,0);
dijkstra(head);
for(int i=1;i<=P;i++){
ans += dis[i];
}
fill(dis,dis+MAX_P,INF);
fill(vis,vis+MAX_P,0);
dijkstra(rhead);
for(int i=1;i<=P;i++){
ans += dis[i];
}
// lld not ld
printf("%lld\n", ans);
}
return 0;
}
Dijkstra更新条件不同于最短路
POJ 2253 minmax distance;
POJ 1797 maxmin distance,距离初始化与minmax恰好相反。
下面只给出 POJ 2253 minmax题目AC解:
#include"stdio.h"
#include"string.h"
#include"math.h"
#include<vector>
#include<queue>
#include<functional>
#include<algorithm>
using namespace std;
typedef pair<int,int> Pair;
const int MAX_N = 203;
int N;
double G[MAX_N][MAX_N];
vector<Pair> pos;
int vis[MAX_N];
double frogd[MAX_N];
double EuDist(Pair p1,Pair p2){
double x=p1.first-p2.first;
double y=p1.second-p2.second;
return sqrt(x*x+y*y);
}
void dijkstra(int s){
frogd[s]=0;
priority_queue<Pair,vector<Pair>,greater<Pair>> Q;
Q.push(Pair(frogd[s],s));
while(!Q.empty()){
Pair p = Q.top();
Q.pop();
int cur = p.second;
/* --------
/* bfs标记vis的位置与push同时操作;
/* dijkstra标记vis的操作在pop之后:
/* 刚push进去的距离可能大于先前就在queue中的,
/* 因此下一个加入vis集合的不一定是刚push进去的
--------*/
if(vis[cur]) continue;
vis[cur]=1;
double tmp_min=G[0][1];
// int tmp_next;
for(int j=0;j<N;j++){
if(j==cur) continue;
if(G[cur][j]==-1) continue;
if(vis[j]) continue;
if(max(frogd[cur],G[cur][j]) < frogd[j]) {
frogd[j] = max(G[cur][j],frogd[cur]);
Q.push(Pair(frogd[j],j));
}
}
}
}
int main(){
int t=0;
while(scanf("%d",&N)!=EOF){
t++;
if(N==0) break;
pos.clear();
// do not use memset!
fill(G[0],G[0]+MAX_N*MAX_N,-1);
fill(vis,vis+MAX_N,0);
fill(frogd,frogd+MAX_N,999999999);
for(int n=0;n<N;n++){
int x,y;
scanf("%d %d",&x,&y);
pos.push_back(Pair(x,y));//0-Freaddy, 1-Fiona
}
for(int i=0;i<N-1;i++){
for(int j=i+1;j<N;j++){
G[i][j]=G[j][i] = EuDist(pos[i],pos[j]);
}
}
dijkstra(0);
printf("Scenario #%d\n", t);
printf("Frog Distance = %.3f\n", frogd[1]);
printf("\n");
}
return 0;
}
反向Dijkstra
POJ 3268 Silver Cow Party
求任一点和X的往返距离:每个点作为源进行一次dijkstra会TLE;事实上只用两遍Dijkstra(正向和反向)。
下面给反向DijsktraAC代码,其中数据初始化和正向相同,只有判断和更新条件略不同。
fill(disDst,disDst+MAX_N,0x3fffffff);
void dijkstraDst(int dst){
disDst[dst]=0;
priority_queue<Pair,vector<Pair>,greater<Pair>> Q;// min-heap
Q.push(Pair(disDst[dst],dst));
while(!Q.empty()){
Pair p = Q.top();
Q.pop();
int cur = p.second;
if(vis[cur]) continue;
vis[cur] = 1;
for(int i=1;i<=N;i++){
if(G[i][cur]==-1) continue;
if(disDst[cur]+G[i][cur] < disDst[i]){
disDst[i] = disDst[cur]+G[i][cur];
Q.push(Pair(disDst[i],i));
}
}
}
}