POJ 1847 全部算法 图论

Tram

Time Limit: 1000MS

Memory Limit: 30000K

Total Submissions: 8553

Description

Tram network in Zagreb consists of anumber of intersections and rails connecting some of them. In everyintersection there is a switch pointing to the one of the rails going out ofthe intersection. When the tram enters the intersection it can leave only inthe direction the switch is pointing. If the driver wants to go some other way,he/she has to manually change the switch.

When a driver has do drive from intersection A to the intersection B he/shetries to choose the route that will minimize the number of times he/she willhave to change the switches manually.

Write a program that will calculate the minimal number of switch changesnecessary to travel from intersection A to intersection B.

Input

The first line of theinput contains integers N, A and B, separated by a single blank character, 2<= N <= 100, 1 <= A, B <= N, N is the number of intersections inthe network, and intersections are numbered from 1 to N.

Each of the following N lines contain a sequence of integers separated by asingle blank character. First number in the i-th line, Ki (0 <= Ki <=N-1), represents the number of rails going out of the i-th intersection. NextKi numbers represents the intersections directly connected to the i-thintersection.Switch in the i-th intersection is initially pointing in thedirection of the first intersection listed.

Output

The first and onlyline of the output should contain the target minimal number. If there is noroute from A to B the line should contain the integer "-1".

SampleInput

3 2 1

2 2 3

2 3 1

2 1 2

SampleOutput

0

Source


Croatia OI 2002 Regional -Juniors



题解:
题目的大致内容是:给定一个有向无环图,求源点到终点的距离最短。
很裸的一个最短路,刚好来测试。


//Floyd();        // O(v^3)             16 ms
//Dijkstra_A();    // O(v*e)             0  ms
//Dijkstra_B();    // O((v+e)log e)       0  ms
//BellmanFord();   // O(v*e)             0  ms
//Spfa_A();       // O(ke)              16 ms
//Spfa_B();       // O(ke)              0  ms


首先是floyd算法,本来是用来求多源的,但是题目数据太弱,所以。。呵呵,顺便也能求。O( n^3 )的复杂度。必然时间很多。
下来是不优化的dijkstra,时间复杂度是O(v*e) ,已经可以0ms过了。
再来是用堆优化的dijkstra,利用的是效率比较低的STL中的priority_queue,已经。。0ms
后面的是bellmamford,和不优化的dijkstra是一个时间复杂度。但是可以处理负环问题,明显优于dijkstra的不优化版本。0ms。
下面是bellmanford的队列优化算法,即spfa算法的普通版,O(ke)的时间复杂度,k经过验证一般小于2,这时间复杂度的确和他的名字相符。。敢叫做ShortestPathFasterAlgorithm,肯定有过人之处,作为中国人发明的算法,必须顶。。。。但是。很明显STL的queue时间复杂度。。。呵呵。。。16ms还是裸写queue吧

最后登场的是用slf优化的spfa。。。时间复杂度理论值还是O(ke),但是实际上是有很明显的优化效率的。在使用慢的要死的STL deque的情况下,依然表现完美。0 ms。

源代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#define INF 999999
#define N 110
using namespace std;

class Node{
    public :
    int x,z,y;
    friend bool operator >(const Node &p,const Node &q){
        return (p.z>q.z);
    }
}ss,bf[N*N];
priority_queue <Node,vector<Node>,greater<Node> > sp;
int a[N+1][N+1];
int f[N+1];
int n,s,e,m,num;
queue <int> pa;
deque <int> ap;
int dis[N+1];

void readin(){
    scanf("%d%d%d",&n,&s,&e);
    int i,j;
    int x,y;
    for (i=1;i<=n;i++)
    for (j=1;j<=n;j++)
    a[i][j]=INF;
    for (i=1;i<=n;i++){
        scanf("%d",&m);
        for (j=1;j<=m;j++){
            scanf("%d",&x);
            if (j==1) a[i][x]=0;
            else
            a[i][x]=1;
            ss.x=i,ss.z=a[i][x],ss.y=x;
            bf[++num]=ss;
        }
    }
    for (i=1;i<=n;i++){
        ss.x=i,ss.z=a[s][i];
        dis[i]=INF;
        sp.push(ss);
    }
}

void Floyd(){
    int i,j,k;
    for (k=1;k<=n;k++)
    for (i=1;i<=n;i++)
    for (j=1;j<=n;j++){
        if (a[i][k]<INF && a[k][j]<INF){
            a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
        }
    }
    if (a[s][e]==INF) puts("-1");
    else
    printf("%d\n",a[s][e]);
}

void Dijkstra_A(){
    memset(f,0,sizeof(f));
    f[s]=1;
    int i,k;
    int mm;
    int w;
    for (k=1;k<n;k++){
        mm=INF;
        for (i=1;i<=n;i++){
            if (!f[i] && a[s][i]<=mm){
                mm=a[s][i];
                w=i;
            }
        }
        f[w]=1;
        for (i=1;i<=n;i++){
            if (!f[i] && a[s][w]<INF && a[w][i]<INF){
                a[s][i]=min(a[s][i],a[s][w]+a[w][i]);
            }
        }
    }
    if (a[s][e]==INF) puts("-1");
    else
    printf("%d\n",a[s][e]);
}

void Dijkstra_B(){
    memset(f,0,sizeof(f));
    f[s]=1;
    int i,k;
    int mm;
    int w;
    for (k=1;k<n;k++){
        while (f[sp.top().x]) sp.pop();
        f[sp.top().x]=1;
        for (i=1;i<=n;i++){
            if (!f[i] && a[s][sp.top().x]+a[sp.top().x][i]<a[s][i]){
                a[s][i]=a[s][sp.top().x]+a[sp.top().x][i];
                ss.x=i,ss.z=a[s][i];
                sp.push(ss);
            }
        }
    }
    if (a[s][e]==INF) puts("-1");
    else
    printf("%d\n",a[s][e]);
}

void BellmanFord(){
    int i,j;
    for (i=1;i<n;i++){
        for (j=1;j<=num;j++){
            a[s][bf[j].y]=min(a[s][bf[j].x]+bf[j].z,a[s][bf[j].y]);
        }
    }
    if (a[s][e]==INF) puts("-1");
    else
    printf("%d\n",a[s][e]);
}

void Spfa_A(){
    int i,j,k;
    pa.push(s);
    f[s]=1;
    dis[s]=0;
    while (!pa.empty()){
       k=pa.front();
       pa.pop();
       for (j=1;j<=n;j++){
           if (dis[j]>dis[k]+a[k][j]){
               dis[j]=dis[k]+a[k][j];
               if (!f[j]){
                   f[j]=1;
                   pa.push(j);
               }
           }
       }
       f[k]=0;
    }

    if (dis[e]==INF) puts("-1");
    else
    printf("%d\n",dis[e]);
}

void Spfa_B(){
    int i,j,k;
    ap.push_back(s);
    f[s]=1;
    dis[s]=0;
    while (!ap.empty()){
       k=ap.front();
       ap.pop_front();
       for (j=1;j<=n;j++){
           if (dis[j]>dis[k]+a[k][j]){
               dis[j]=dis[k]+a[k][j];
               if (!f[j]){
                   f[j]=1;
                   if (!ap.empty()){
                   if (dis[j]<dis[ap.front()]) ap.push_front(j);
                   else
                   ap.push_back(j);
                   }
                   else
                   ap.push_back(j);
               }
           }
       }
       f[k]=0;
    }

    if (dis[e]==INF) puts("-1");
    else
    printf("%d\n",dis[e]);
}
int main(){
    readin();

    //Floyd();        // O(v^3)             16 ms
    //Dijkstra_A();    // O(v*e)             0  ms
    //Dijkstra_B();    // O((v+e)log e)       0  ms
    //BellmanFord();   // O(v*e)             0  ms
    //Spfa_A();       // O(ke)              16 ms
    //Spfa_B();       // O(ke)              0  ms

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值