您的位置:首页 > 其它

poj 1511 Invitation Cards

2012-09-02 11:17 274 查看
题目地址: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: