一只菜鸡的图论之路

从最简单的dijkstra


这里先读的
题目 HDU 2544
自己照着自己关于dijkstra的理解写的代码T了。1

bool allvis() {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += vis[i];
    }
    if (sum == n) {
        return true;
    } else {
        return false;
    }
}
void dijkstra(int start) {
    memset(vis, 0, sizeof(vis));
    vis[start] = 1;
    while (!allvis()) {
        int mincost = MAXNUM;
        int nextpos = 0;
        for (int i = 0; i < n; i++) {
            if (cost[start][i] < mincost && vis[i] == 0) {
                mincost = cost[start][i];
                nextpos = i;
                vis[i] = 1;
            }
        }
        for (int i = 0; i < n; i++) {
            if (vis[i] == 0) {
                if (cost[nextpos][i] + cost[start][nextpos] < cost[start][i]) {
                    cost[start][i] = cost[nextpos][i] + cost[start][nextpos];
                }
            }
        }
    }
}

判断条件我选择了是所有的点都被遍历一遍,(脑残)。
由于每次 vis[] 中必定会多出一个点,所以只需要遍历 n 次。
别人的代码

bool vis[102];//判断顶点是否被访问过,需要初始化  
int d[102];//保存从起点到编号为i的顶点的最短距离d[i]  
int w[102][102];//边的价值,w[from][to]   
int n,m;//n为顶点数,m为边数  

void dijkstra(int start)//最短路dijkstra算法  
{  
    memset(vis,0,sizeof(vis));  
    for(int i=1;i<=n;i++)  
        d[i]=(i==start?0:inf);//初始化,起点d[start]=0, 其它均为最大值,inf  
    for(int i=1;i<=n;i++)  
    {  
        int x,mini=inf;//x为未访问过的d[i]存在最小值的那个顶点编号,每次都需要找这个顶点,找n次  
        for(int y=1;y<=n;y++)  
            if(!vis[y]&&d[y]<=mini)  
            {  
                mini=d[y];  
                x=y;//两句可以合写为mini=d[x=y];  
            }  
        vis[x]=1;//找到的顶点被访问过  
        for(int y=1;y<=n;y++)  
            d[y]=min(d[y],d[x]+w[x][y]);
    }  
}  

然后分析别人代码的时候,明白了上午熊猫讲的优化问题,因为每次都要从 cost[] 中找出最小的且未被标记的点。

自己写的代码,刚好最近健行男神讲了优先队列。看着kuangbin的代码自己理解了之后写的。
WA了一发,错在了

if (cost[temp.v][i] + pos[temp.v]< pos[i]) {
        pos[i] = cost[temp.v][i] + pos[temp.v];
        que.push(qnode(i, pos[i]));
}

还是不是自己完全理解的东西是不自己的。 pos[temp.v] 用的是 cost[start][temp.v] ,这个代码的更新的是 pos[]

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int inf = 1 << 30;
bool vis[102];
int pos[102];
int cost[102][102];
struct qnode {
    int v;
    int c;
    qnode(int _v = 0, int _c = 0) :
            v(_v), c(_c) {
    }
    bool operator<(const qnode &r) const {
        return c > r.c;
    }
};
int n, m;
priority_queue<qnode> que;
void dijkstra(int start) {
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= n; i++)
        pos[i] = (i == start ? 0 : inf);
    while (!que.empty()) {
        que.pop();
    }
    que.push(qnode(start, 0));
    qnode temp;
    while (!que.empty()) {
        temp = que.top();
        que.pop();
        if (vis[temp.v])
            continue;
        vis[temp.v] = 1;
        for (int i = 1; i <= n; i++) {
            if (vis[i] == 0) {
                if (cost[temp.v][i] + pos[temp.v]< pos[i]) {
                    pos[i] = cost[temp.v][i] + pos[temp.v];
                    que.push(qnode(i, pos[i]));
                }
            }
        }
    }
}
int main() {
    //freopen("in.txt", "r", stdin);
    while (cin >> n >> m && n && m) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                    cost[i][j] = inf;
            }
        }
        for (int i = 1; i <= m; i++) {
            int from, to, co;
            cin >> from >> to >> co;
            if (cost[from][to] > co) {
                cost[from][to] = co;
                cost[to][from] = co;
            }
        }
        dijkstra(1);
        cout << pos[n] << endl;
    }
    return 0;
}

kuangbin 的模板:


/*
使用优先队列优化Dijkstra算法
复杂度O(ElogE)
注意对vector<Edge>E[MAXN]进行初始化后加边
*/
const int INF=0x3f3f3f3f;
const int MAXN=1000010;
struct qnode
{
    int v;
    int c;
qnode(int _v=0,int _c=0):v(_v),c(_c){}
bool operator <(const qnode &r)const
{
    return c>r.c;
}
};
struct Edge
{
    int v,cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[MAXN];
bool vis[MAXN];
int dist[MAXN];
void Dijkstra(int n,int start)//点的编号从1开始
{
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++)
        dist[i]=INF;
    priority_queue<qnode>que;
    while(!que.empty())
        que.pop();
    dist[start]=0;
    que.push(qnode(start,0));
    qnode tmp;
    while(!que.empty())
    {
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u])
            continue;
        vis[u]=true;
        for(int i=0;i<E[u].size();i++)
        {
            int v=E[tmp.v][i].v;
            int cost=E[u][i].cost;
            if(!vis[v]&&dist[v]>dist[u]+cost)
            {
                dist[v]=dist[u]+cost;
                que.push(qnode(v,dist[v]));
            }
        }
    }
}

按照这种思路又改了一遍,因为考虑了一下,关于找邻接点的时候全部遍历效率还是 n 2   的效率。在构造图的时候以点的邻接点构造,WA了一发,E[MAXN]进行初始化后加边。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值