zoukankan      html  css  js  c++  java
  • poj 1511 Invitation Cards

    题目地址:http://poj.org/problem?id=1511

    方法一:

    /*
    	本题使用邻接表采用动态开辟的方式保存所有的边,首先定义一个保存指向的顶点和边所对应权值,
    */
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define NMAX_D 1000005
    #define NMAX 1000000001
    int n,m;
    //定义结构体
    struct node
    {
    	int v,cost;
    	node *next;
    }edge[NMAX_D],redge[NMAX_D];//定义两个数组,edge用来保存顺向边,redge保存逆向边
    bool vis[NMAX_D];//标记数组,用来标记结点i是否已经在队列里面,防止重复对同一节点进行扩展
    int dis[NMAX_D];//保存起点到目标结点的距离
    __int64 sum;//用来保存总的费用,显然最后结果很可能超int
    queue<int> Q;
    void release(node edge[])//初始化结点,分离出所有结点
    {
    	node *p,*q;
    	for(int i = 1; i <= n; i++)
    	{
    		p = &edge[i];
    		while(p->next)
    		{
    			q = p->next;
    			p->next = q->next;
    			free(q);
    		}
    	}
    }
    void init()//输入各边关系和边所对应的权值。并构造邻接表
    {
    	int a,b,c;
    	node *p,*q;
    	release(edge);
    	release(redge);
    	for(int i = 0; i < m;i++ )
    	{
    		scanf("%d%d%d",&a,&b,&c);
    		q = (node*)malloc(sizeof(node));
    		q->v = b;
    		q->cost = c;
    		p = &edge[a];
    		q->next = p->next;
    		p->next = q;
    
    
    		q = (node*)malloc(sizeof(node));
    		q->v = a;q->cost = c;
    		p = &redge[b];
    		q->next = p->next;
    		p->next = q;
    	}
    }
    
    //spfa算法,求最短路径
    void psfa(node edge[])
    {
    	int i;
    	//初始化数组vis和数组dis
    	memset(vis,false,sizeof(vis));
    	for(i = 0; i <= n; i++)
    		dis[i] = NMAX;
    	dis[1] = 0;
    	vis[1] = true;//标记1号结点已经在队列中
    	Q.push(1);//第一个顶点进队列
    	while( !Q.empty())
    	{
    		int now = Q.front();//取队头元素
    		Q.pop();//队头元素出队列
    		vis[now] = false;//标记now结点为不在队列中
    		for(node *p = edge[now].next; p ; p = p->next)
    		{
    			if(dis[p->v] > dis[now] + p->cost)//求当存在大结点p->v更短的路径时,更新从起点到p->v的路径
    			{
    				dis[p->v] = dis[now] + p->cost;
    				if(!vis[p->v])//当结点p->v已经在队列中则不再进队列
    				{
    					vis[p->v] = true;
    					Q.push(p->v);
    				}
    			}
    		}
    	}
    	for(i = 1; i <= n; i++)sum += dis[i];
    }
    int main()
    {
    	int t;
    	scanf("%d",&t);
    	while( t-- )
    	{
    		scanf("%d%d",&n,&m);
    		init();
    		sum = 0;
    		psfa(edge);
    		psfa(redge);
    		printf("%I64d\n",sum);
    	}
    	return 0;
    }


    方法二:

    用SPFA,又加了点优化用SLF。

    /*
    	采用邻接表的变形版本保存,用两个指针数组保存结点,用一个连续的一维数组保存边,
    	起于同一顶点的边用指针连接。
    */
    #include<stdio.h>
    #include<string.h>
    #include<deque>
    using std::deque;
    #define INF (1<<30)
    #define MAXN 1000001
    //用来保存数据的结构体
    struct node
    {
    	int v,cost;
    	node *next;
    };
    //*head1[]和*head[]均为保存结点的指针数组,edge,和redge两个数组用来保存
    node *head1[MAXN],*head[MAXN],edge[MAXN],redge[MAXN],*p1,*q1;
    
    int n,m,dis[MAXN];
    bool vis[MAXN];
    deque<int>Q;
    __int64 sum;
    void init()
    {
    	int i,a,b,c;
    	p1 = edge,q1 = redge,sum = 0;
    	for(i = 0; i <= n; i++)head1[i] = head[i] = NULL;
    	for(i = 0; i < m; i++)
    	{
    		scanf("%d%d%d",&a,&b,&c);
    		p1->v = b;p1->cost = c;
    		p1->next = head[a];
    		head[a] = p1++;
    
    		q1->v = a;q1->cost = c;
    		q1->next = head1[b];
    		head1[b] = q1++;
    	}
    }
    void spfa(bool is)
    {
    	int i ;
    	memset(vis,false,sizeof(vis));
    	for(i = 2; i <= n; i++)dis[i] = INF;
    	dis[1] = 0;
    	vis[1] = true;
    	Q.push_front(1);
    	while( !Q.empty() )
    	{
    		int now = Q.front();
    		Q.pop_front();
    		vis[now] = false;
    		for(p1 = (is) ? head[now] : head1[now] ; p1; p1 = p1->next)
    		{
    			if(dis[p1->v] > dis[now] +p1->cost)
    			{
    				dis[p1->v] = dis[now] + p1->cost;
    				//p1->v进队列
    				if( !Q.empty() && dis[p1->v] < dis[Q.front()])
    					Q.push_front(p1->v);
    				else
    					Q.push_back(p1->v);
    				vis[p1->v] = true;
    			}
    		}
    	}
    	for(i = 1; i <= n; i++)sum += dis[i];
    }
    int main()
    {
    	int t;
    	scanf("%d",&t);
    	while( t-- )
    	{
    		scanf("%d%d",&n,&m);
    		init();
    		spfa(true);
    		spfa(false);
    		printf("%I64d\n",sum);
    	}
    	return 0;
    }
    


     

  • 相关阅读:
    整数m去掉n位后剩下最大(小)值
    蛇形矩阵(二)
    Kibana源码启动报错记录--ENOSPC
    Kibana问题记录:yarn test 运行报错 error Trailing spaces not allowed no-trailing-spaces
    Vim 编辑器中全选操作
    Ubuntu系统中连接TFS的Git地址注意事项
    Ubuntu系统升级遇到问题记录
    Kibana6.2.x 插件理解
    Kibana问题搜集---下载源码,执行npm install 报错
    Kibana6.2.2源码入口
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3220865.html
Copyright © 2011-2022 走看看