Orz,做这道题对我这个初学者来说真是呕心沥血了!写了一上午,然后调试了一下午。然后WA了3次!哇靠,就是因为坑爹的POJ数据,题目明白说了price的sum不会超int的
但最后还是要用long long 才过!奶娘的! 在这里感谢羽哥的数据还有long long的提醒。
题目大意:发传单!怎么样选择路线 使得Acmers们在去 和回的过程 花掉的车费最少。
思路:因为每个人负责一站,其实人在这里只是幌子,只要找出出发点到每个站的最短路径(就是最少花费),那么每个人的的花费总和也会最小。回来的时候同理
因为在这里的数据很大。V、 E都达到100W,用朴素的dijkstra已经不行,用堆优化的,我不会(囧)。bellman 算法也不可行了。因为是O(VE)效率。只能选择O(kE)的SPFA算法了(k<=2)
PS: SPFA判断有无负环很简单,就是:用一个数组记录每个节点的入队次数,如果入队次数到达节点总数N那么就有负权环。
program:
#include<cstdio>
#include<queue>
#include<iostream>
#include<string.h>
using namespace std;
#define maxn 1000005
#define inf 1500000000
int visited[maxn],dis[maxn],st[maxn];
int test,n,m;
int u[maxn],v[maxn],w[maxn];
struct node
{
int x;
int value;
int next;
}e[maxn];
void spfa() // int
{
for(int i=1;i<=n;i++)
{
visited[i]=0;//杯具啊,一开始写成1了。囧
dis[i]=inf;
}
visited[1]=1;
dis[1]=0;
queue<int>que;
que.push(1);
int tmp=st[1];
int cur;
int k=0;
while(!que.empty())
{
cur=que.front();
tmp=st[cur]; // 同样Qrz,一开始竟然没有。囧
que.pop();
visited[cur]=0; //一出队就重新吧标志擦去,这是SPFA和BFS最大的区别,下面基本上和BFS的相似度极大
while(tmp!=0)
{
if(dis[e[tmp].x]>dis[cur]+e[tmp].value)
{
dis[e[tmp].x]=dis[cur]+e[tmp].value;
if(visited[e[tmp].x]==0)
{
que.push(e[tmp].x);
visited[e[tmp].x]=1;
// printf(" e[tmp].x %d \n",e[tmp].x) ;
}
}
// printf("tmp e[tmp].next %d %d \n",tmp,e[tmp].next) ;
tmp=e[tmp].next;
}
}
}
void ini()
{
memset(e,0,sizeof(e));
memset(st,0,sizeof(st));
for(int i=1;i<=m;i++)
{
e[i].x=v[i];
e[i].value=w[i];
e[i].next=st[u[i]];
st[u[i]]=i;
//printf("i e[i].next %d %d \n",i,e[i].next) ;
//printf("i u e[st[u]].x e[st[u]].value %d %d %d %d \n",i,u,e[st[u]].x,e[st[u]].value);
//一开始的邻接表也很Orz啊。呜呜。。
//stu就是头结点指针(指向第一个边表节点,在插入的过程中可能不断变化),
//next是边表指针,e[I].x就是保存边表节点数据的
}
}
void reini()
{
memset(e,0,sizeof(e));
memset(st,0,sizeof(st));
for(int i=1;i<=m;i++)
{
//scanf("%d%d%d",&u,&v,&w); //redirction
e[i].x=u[i];
e[i].value=w[i];
e[i].next=st[v[i]];
st[v[i]]=i;
//printf("i e[i].next %d %d \n",i,e[i].next) ;
}
}
int main()
{
scanf("%d",&test);
while(test--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&u[i],&v[i],&w[i]); //一开始我只是那寻常变量来保存3个东东,囧。。。
//memset(e,0,sizeof(e));//
ini();
spfa();
long long sum=0;
for(int i=1;i<=n;i++)
sum+=dis[i];
reini(); //来回都来一次SPFA
spfa();
for(int i=1;i<=n;i++)
sum+=dis[i];
printf("%lld\n",sum); //最悲剧是这里,上面改了long long 但是,输出的时候却没改限制。囧
}
//system("pause");
return 0;
}