传送门:
http://poj.org/problem?id=1511
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1008
题目大意:
给定p个点,还有他们的边q,(有向图)求从结点1出发到所有结点和所有结点到1的最短路径之和。
其中1 <= P,Q <= 1000000
思路:
和上次 POJ 3268 Silver Cow Party 一样,有向图倒着建立就把从所有结点到1的最短路径改为了从1到所有,那么只需两次dijkstra即可。
还有就是数据量大,要用优先队列的dijkstra,堆优化的更好。
嗯,第一次写这个,参考了别人的。
code1:2014/1/1更新。。。
今天自己写的------
直接用数组模拟链表快了好多,zoj排名挺靠前面的,嘻嘻,不过poj又被虐。。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=1000000+10;
bool vis[MAXN];
int head[2][MAXN];
int n,m;
long long ans;
struct edge
{
int to;
int cost;
int next;
}e[2][MAXN];
struct node
{
int from;
int cost;
node(int f,int c){from=f;cost=c;}
bool operator < (const node& b)const
{
return cost > b.cost;
}
};
int len;
void insert(int from,int to,int cost)
{
e[0][len].to=to;
e[1][len].to=from;
e[0][len].cost=e[1][len].cost=cost;
e[0][len].next = head[0][ from ];
e[1][len].next = head[1][ to ];
head[0][from]=len;
head[1][to]=len;
len++;
}
void dijkstra(int kind)
{
memset(vis,0,sizeof(vis));
priority_queue<node> q;
q.push(node(1,0));
int num=0;
while(!q.empty())
{
node cur=q.top();
q.pop();
if(vis[cur.from]==true) continue;
vis[cur.from]=true;
ans+=cur.cost;
num++;
if(num==n)
break;
//这里写得真纠结- -|||
for(int ne=head[kind][cur.from];ne!=-1;ne=e[kind][ ne ].next)
{
if(!vis[e[kind][ ne ].to])
q.push(node(e[kind][ ne ].to,e[kind][ ne ].cost+cur.cost));
}
}
}
int main()
{
int T;
scanf("%d",&T);
int from,to,cost;
while(T--)
{
len=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&from,&to,&cost);
insert(from,to,cost);
}
ans=0;
dijkstra(0);
dijkstra(1);
printf("%lld\n",ans);
}
return 0;
}
code 2:
2013/12/31第一次写,基本上是模仿别人的
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=1000000+10;
long long ans;
bool vis[MAXN];
int n,m;
struct edge
{
int to,cost;
edge* next;
edge(){next=NULL;}
}*e[2][MAXN];
struct node
{
int cost,id;
bool operator < (const node& b) const
{
return cost>b.cost;
}
node(int i,int c){ cost =c;id=i;}
};
inline void addedge(int from,int to,int cost)
{
edge *p=new edge;
edge *q=new edge;
p->next=e[0][from];
q->next=e[1][to];
p->to=to;
q->to=from;
p->cost=q->cost=cost;
e[0][from]=p;
e[1][to]=q;
}
void dijkstra(int kind)
{
memset(vis,0,sizeof(vis));
priority_queue<node> q;
int num=0;
node cur(1,0);
q.push(cur);
while(!q.empty())
{
cur=q.top();
q.pop();
if(vis[cur.id]==true)
continue;
vis[cur.id]=true;
ans+=cur.cost;
num++;
if(num==n)
break;
for(edge *p=e[kind][cur.id];p!=NULL;p=p->next)
{
if(vis[p->to]==false)
{
node temp(p->to,p->cost+cur.cost);
q.push(temp);
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(e,NULL,sizeof(e));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int from,to,cost;
scanf("%d%d%d",&from,&to,&cost);
addedge(from,to,cost);
}
ans=0;
dijkstra(0);
dijkstra(1);
printf("%lld\n",ans);
}
return 0;
}