POJ 1511 Invitation Cards(SPFA)
http://poj.org/problem?id=1511
题意:
有一个N个点的有向图,点的编号从1到N.现在要你求从1号点到所有其他点的最短距离S1+ 从所有其他点到1号点的最短距离S2的值.
分析:
求其他点到1号点的最短距离直接建立原图的反向图然后求最短路径即可.
直接利用SPFA求解.注意最终结果ans要用long long.
注意:此题数据高达100W,所以如果用带vector的SPFA就会超时,这里只能用我们自己实现的邻接表来保存边的信息.具体看代码.
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define INF 1e9
using namespace std;
const int maxn =1000000+10;
int n,m;
struct Edge
{
int from,to,dist;
Edge(){}
Edge(int f,int t,int d):from(f),to(t),dist(d){}
};
struct BellmanFord
{
int n,m;
int head[maxn]; //每个节点邻接表的头
int next[maxn];
Edge edges[maxn]; //所有的边信息
bool inq[maxn];
int d[maxn];
int p[maxn];
int cnt[maxn];
void init(int n)
{
this->n=n;
this->m=0;
memset(head,-1,sizeof(head));
}
void AddEdge(int from,int to,int dist)
{
edges[m]=Edge(from,to,dist);
next[m]=head[from];
head[from] = m++;
}
bool negativeCycle(int s)
{
queue<int> Q;
memset(inq,0,sizeof(inq));
memset(cnt,0,sizeof(cnt));
for(int i=0;i<n;i++) d[i]= i==s?0:INF;
Q.push(s);
while(!Q.empty())
{
int u=Q.front(); Q.pop();
inq[u]=false;
for(int i=head[u];i!=-1;i=next[i])
{
Edge &e=edges[i];
if(d[e.to] > d[u]+e.dist)
{
d[e.to] = d[u]+e.dist;
p[e.to] = i;
if(!inq[e.to])
{
inq[e.to]=true;
Q.push(e.to);
if(++cnt[e.to]>n) return true;
}
}
}
}
return false;
}
}BF1,BF2;
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
BF1.init(n), BF2.init(n);
while(m--)
{
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
u--,v--;
BF1.AddEdge(u,v,d);
BF2.AddEdge(v,u,d);
}
BF1.negativeCycle(0);
BF2.negativeCycle(0);
long long ans=0;
for(int i=1;i<n;i++)
ans += BF1.d[i]+BF2.d[i];
printf("%I64d\n",ans);
}
return 0;
}