zoukankan      html  css  js  c++  java
  • pku 2387 Til the Cows Come Home

    用spfa做,额,到目前为止做的题目都几乎是模板题,三四道都是改一下输入就了事了,不过针对题目而已,还真有选择的余地,这里一个是我的,额,内存开得太大了,主要是1000*1000的矩阵来保存一个图的信息,本来很明显的得用邻接表来储存的,,而且只保存有用的边,而且加上用队列优化,快了不少呢

    对比一下俩个代码吧

    用邻接表的:

    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define N  4000
    struct edge{
        int v,next,cost;
    	edge(int _v=0 ,int _next=0,int _cost=0):v(_v),next(_next),cost(_cost){};
    }e[N];
    int dist[N];
    int n,m,p[N],tot = 0;
    void spfa(int s)
    {
        bool vist[N];
        memset(vist,false ,sizeof(vist));
        memset(dist,1,sizeof(dist));
        dist[s] = 0;
        int que[N];
        int begin,end;
        begin = end = 0;
        que[end++] = s;
        vist[s] = true;
        while(begin<end)
        {
            int t = que[begin++];
            vist[t] = false;
            for(int j = p[t];j!=-1;j = e[j].next)
            {
    
                if(dist[e[j].v]>e[j].cost+dist[t])
    
                {
                    dist[e[j].v] = e[j].cost+dist[t];
                    if(!vist[e[j].v])
                    {
                        vist[e[j].v] = true;
                        que[end++] = e[j].v;
    
                    }
                }
            }
        }
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            tot = 0;
            memset(p,-1,sizeof(p));
            int a,b,c;
            for(int i = 0;i<n;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
    	        e[tot]=edge(b,p[a],c);
                p[a] = tot++;
                e[tot]=edge(a,p[b],c);
                p[b] = tot++;
            }
            spfa(1);
            printf("%d\n",dist[m]);
    
        }
    }
    

    直接用邻接矩阵保存的:

    #include<iostream>
    #define MAXINT 999999
    using namespace std;
    int m,n;
    int dis[1001],Q[10010],vis[1001];
    int map[1001][1001];
    void SPFA(int n, int s)
    {
    	// pri是队列头结点,end是队列尾结点
        int i, pri, end, p;
        memset(vis, 0, sizeof(vis));
        for(int i=0; i<10010; ++i)
            Q[i] = 0;
        for (i=1; i<=n; i++)
            dis[i] =MAXINT;
        dis[s] = 0;
        vis[s] = 1;
        Q[1] = s; pri = 1; end = 2;
        while (pri < end)
        {
            p = Q[pri];
            for (i=1; i<=n; ++i)
            {
    			//更新dis
                if (dis[p]+map[p][i] < dis[i])
                {
                    dis[i] = dis[p]+map[p][i];
                    if (!vis[i])     //未在队列中
                    {
                        Q[end++] = i;
                        vis[i] = 1;
                    }
                }
            }
            vis[p] = 0;   // 置出队的点为未标记
            pri++;
        }
    } 
    
    int main()
    {
    	while(cin>>m>>n)
    	{
    		int a,b,len;
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				map[i][j]=MAXINT;
    		for(int i=1;i<=m;i++)
    		{
    			cin>>a>>b>>len;
    			if(map[a][b]>len)
    			{
    				map[a][b]=len;
    				map[b][a]=len;
    			}
    		}
    		SPFA(n,1);
    	cout<<dis[n]<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    面试金典——模式匹配
    浅谈C语言中的联合体
    android recovery模式及ROM制作
    模拟键盘输入 : SendMessage, keybd_event, PostKeybdMessage
    在游戏中使用keybd_event的问题
    keybd_event函数用法
    C语言清空输入缓冲区的N种方法对比
    深究“字节对齐”的原因
    字节对齐
    网络安装CentOS 5.3
  • 原文地址:https://www.cnblogs.com/nanke/p/2136868.html
Copyright © 2011-2022 走看看