http://poj.org/problem?id=1511
题目大意:一群人从七点出发到各个点的花费,是一副有向图,可以构造正向与反向两幅图,然后用spfa加邻接表、、接下来几天我得给floyd、bellmanford 、dijkstra、spfa好好做个总结。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define ll __int64
#define inf 4000000000
struct edge{
ll next;
ll to;
ll side;
};
edge e[1000002],e1[1000002];
ll p1[1000002], p2[1000002];
ll head[1000002], tot,tot1,head1[1000002];
int k[1000002];
void add(ll a, ll b, ll c)
{
e[tot].to=b;
e[tot].side=c;
e[tot].next=head[a];
// printf("e[%I64d]=head1[%I64d]=%I64d ",tot,a,head[a]);//把输入的各项值保存下来其实这边add与add1其实只要一个就行,
// printf("%I64d",a);
head[a]=tot++;
// printf("head[%I64d]=%I64d",a,tot);
// printf("\n");
}
void add1(ll a, ll b, ll c)
{
e1[tot1].to=b;
e1[tot1].side=c;
e1[tot1].next=head1[a];
// printf("%I64d\n",head1[a]);
// printf("e1[%I64d]=head1[%I64d] ",tot1,a,head1[a]);
head1[a]=tot1++;
// printf("head1[%I64d]=%I64d",a,tot1-1);
// printf("\n");
}
int main()
{
ll N;
scanf("%I64d",&N);
ll i,j;
for(i=1;i<=N;i++)
{
ll P,Q;
tot=0;
tot1=0;
scanf("%I64d%I64d",&P,&Q);
for(j=1;j<=P;j++)
{
//e[j].side=inf;
head[j]= -1;
head1[j]=-1;
}
// printf("%I64d\n",head[1]);
for(j=1;j<=Q;j++)
{
ll a,b,c;
scanf("%I64d%I64d%I64d",&a,&b,&c);
add(a,b,c);
add1(b,a,c);
}
for(j=1;j<=P;j++)
{
p1[j]=inf;
p2[j]=inf;
k[j]=0;
}
p1[1]=0;
p2[1]=0;
queue<ll> q;//队列
q.push(1); //放入起始点
while(!q.empty())
{
int t;
t=q.front();
q.pop();
k[t]=0;
for(j=head[t];j!=-1;j=e[j].next)
{
ll p=e[j].to;
if(p1[p]>p1[t]+e[j].side)
{
p1[p]=p1[t]+e[j].side;
if(k[p]==0)
{
q.push(p);
k[p]=1;
}
}
}
}
//while(!q.empty())
// q.pop();
// printf("%I64d",p1[P-1]);
q.push(1);
for(j=1;j<=P;j++)
k[j]=0;
while(!q.empty())
{
int t;
t=q.front();
q.pop();
k[t]=0;
for(j=head1[t];j!=-1;j=e1[j].next)
{//printf("123");
ll p=e1[j].to;
if(p2[p]>p2[t]+e1[j].side)
{
p2[p]=p2[t]+e1[j].side;
if(k[p]==0)
{
q.push(p);
k[p]=1;
}
}
}
}
ll sum=0;
for(j=2;j<=P;j++)
sum+=p1[j]+p2[j];
printf("%I64d\n",sum);
}
return 0;
}
/*
1
2 2
1 2 13
2 1 33
1
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50
*/