POJ-1847 最短路裸题,Floyd, Bellman, Dijkstra, Spfa

POJ 1847

题意:n个点,电车从A到B。每个点可以到其它ki个点,但默认只通往给出的第一个点,如果要到其它点,必须改变轨道方向一次。问A到B最少改变几次轨道方向。

总结:裸裸的最短路,所以,狠狠的把Floyd, Bellman, Dijkstra, Spfa都给撸了一遍。一个字,爽!

// POJ-1847
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<bitset>
#include<vector>
#include<set>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define F(i,a,b)  for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 200;

int n, A, B;
int G[N][N];

void Floyd()      //O(V^3),任意两点间
{
    FF(k,1,n) FF(i,1,n) FF(j,1,n)  {
        G[i][j] = min( G[i][j], G[i][k]+G[k][j] );
    }
    if(G[A][B]==INF) puts("-1");
    else printf("%d\n", G[A][B]);
}

int Q[N*N], dis[N], vis[N];  //Q队列要多开
void Spfa()         //O(kE),k<=2,改进的Bellman,单源,可有负权,可判负环,但感觉有时候有点玄
{
    mes(vis, 0); mes(dis, INF);
    int head=0, tail=1;
    Q[head]=A, dis[A]=0;
    while(head < tail) {
        int u=Q[head];
        vis[u]=1;
        FF(i,1,n) {
            if(G[u][i]!=INF && dis[i]> dis[u]+G[u][i]) {    //G[u][i]!=INF表示e(u,i)这条边存在,也可用个flag[][]数组标记它是否存在
                dis[i]= dis[u]+G[u][i];
                if(vis[i]==0) {   //要判断,因为i这个点如果取过,有可能会再次取到它
                    vis[i]=1, Q[tail++]=i;
                }
            }
        }
        vis[u]=0, head++;   //vis[u]还要变回0,所以可以重复取到这个点
    }
    if(dis[B]==INF) puts("-1");
    else printf("%d\n", dis[B]);
}

int tot;
struct Edge { int u, v, w; } edge[N*N];
void Bellman()       //O(V*E),单源,可有负权,可判负环,但效率非常低
{
    mes(dis, INF);  dis[A]=0;
    while(true) {
        bool update = false;
        F(i,0,tot) {
            Edge e=edge[i];
            if(dis[e.v]> dis[e.u]+e.w) {
                dis[e.v]= dis[e.u]+e.w;
                update=true;
            }
        }
        if(update==false) break;   //如果不能再松驰就跳出
    }
    if(dis[B]==INF) puts("-1");
    else printf("%d\n", dis[B]);
}

int find_min()  //找到dis(A, i)最小的点
{
    int minn=INF, pos=-1;
    FF(i,1,n) if(vis[i]==0 && dis[i]<minn) {
        pos=i, minn=dis[i];
    }
    return pos;
}
void Dijkstra1()     //单源,不能有负权,不优化O(V^2)
{
    mes(vis, 0);  mes(dis, INF);  dis[A]=0;
    int p=find_min();
    while(p!=-1) {
        vis[p]=1;
        FF(i,1,n) if(vis[i]==0 && dis[i]> dis[p]+G[p][i]) {
            dis[i]= dis[p]+G[p][i];
        }
        p=find_min();
    }
    if(dis[B]==INF) puts("-1");
    else printf("%d\n", dis[B]);
}

struct Node {
    int d, id;
    bool friend operator < (const Node &a, const Node &b) {
        return a.d > b.d;
    }
};
void Dijkstra()     //优先队列优化O(Elog(V))
{
    mes(vis, 0);  mes(dis, INF); dis[A]=0;
    priority_queue<Node > PQ;
    PQ.push( (Node){0, A} );
    while(!PQ.empty()) {
        Node pos=PQ.top();  PQ.pop();
        if(vis[pos.id]==1) continue;    //有可能被压入多次,第一次是最小的,后面的就不用再重复计算了
        vis[pos.id]=1;
        FF(i,1,n) if(vis[i]==0) {
            if(dis[i] > dis[pos.id]+G[pos.id][i]) {
                dis[i]= dis[pos.id]+G[pos.id][i];
                PQ.push( (Node){dis[i], i} );
            }
        }
    }
    if(dis[B]==INF) puts("-1");
    else printf("%d\n", dis[B]);
}

int main()
{
    int ki, c;
    mes(G, INF);
    tot=0;
    scanf("%d%d%d", &n, &A, &B);
    FF(i,1,n) {
        scanf("%d", &ki);
        FF(j,1,ki) {
            scanf("%d", &c);
            if(j==1) G[i][c]=0, edge[tot].w=0;
            else G[i][c]=1, edge[tot].w=1;
            edge[tot].u=i, edge[tot++].v=c;
        }
    }
    //Floyd();
    //Spfa();
    //Bellman();
    //Dijkstra1();
    Dijkstra();

    return 0;
}
时间: 2024-10-07 21:07:49

POJ-1847 最短路裸题,Floyd, Bellman, Dijkstra, Spfa的相关文章

poj 1847 最短路简单题,dijkstra

1.poj  1847  Tram   最短路 2.总结:用dijkstra做的,算出a到其它各个点要改向的次数.其它应该也可以. 题意: 有点难懂.n个结点,每个点可通向ki个相邻点,默认指向第一个相邻点,可以改变指向.求一条从A到B的路,使用最少改变路上点的指向的次数. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm>

POJ 1087 最大流裸题 + map

A Plug for UNIX Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15597   Accepted: 5308 Description You are in charge of setting up the press room for the inaugural meeting of the United Nations Internet eXecutive (UNIX), which has an int

POJ 3468 线段树裸题

这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解. 然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了ACdreamer的模板,在此基础上自己用宏定义来精简了一下代码: 1 #include<cstdio> 2 typedef long long LL; 3 #define root int rt, int l, int r 4 #define lson rt*2, l, mid 5 #define

poj 2387 最短路模板题

Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessie needs her beauty sleep, so she wants to get back as quickly as possible. Farmer John's field ha

poj 2823 单调队列裸题

两个队列分别维持最大和最小 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; struct node { int mi,ma; }num[1000010]; int sax[1000010],sin[1000010]; int ida[1000010],idi[1000010]; int main() { int n,m,i,j,k,a; while(~scanf(&

POJ3156 暑假集训-最短路H题floyd http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82829#rank

  http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82829#rank#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> #include<stdlib.h> #include<ctype.h> #include<limits.h> #include<mat

最短路模板题 51nod1459(dijkstra)

1459 迷宫游戏  http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1459 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数.还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间.游戏规定了你的起点和终点房间,你首要目标是从起点尽快到达终点

怒学三算法 POJ 2387 Til the Cows Come Home (Bellman_Ford || Dijkstra || SPFA)

Til the Cows Come Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33015   Accepted: 11174 Description Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the

poj 1847( floyd &amp;&amp; spfa )

http://poj.org/problem?id=1847 一个水题,用来熟悉熟悉spfa和floyd的. 题意:有m条的铁路,要从x,到y, 之后分别就是条铁路与其他铁路的交点.第一个输入的为有n个交点.之后第一个输入的点,当前铁路到这个点是不要转向的,也就是权值为0,其余的权值都为1,求从x到y的最短路,如果到不了输出-1 裸的floyd和spfa: 1 #include <stdio.h> 2 #include <string.h> 3 #define inf 0x3f3f