题目
题解思路
题目数据1e6,锁定(堆优化 迪杰斯特拉 )(nlogn)。
边都是单向的,过去和回来走的路不同,所以我们要正反向建图两次,然后将dis的值全部加起来就行了!
但是1e6貌似用不了vector(太占内存),只能 链式向前星!
介绍下链式向前星
int pot; // 标记边的数
struct edge { //结构体存边
int to,next; //to和w是这个链表的数据 to指 这条边到的地方 w指权值
ll w; //next 是 指向下一条也是这个起点的边的指针 值就是边的编号
}e[1000010],e2[1000010];
int head[1000010]; //起点数组 指向最后一条边的 指针
void add(int a,int b,ll c) //头插法!
{
pot++; //存入边时边数自增
e[pot].to = b; // 将 边的数据读入
e[pot].w = c;
e[pot].next = head[a]; //头插法,指向之前同起点插入的边的编号
head[a] = pot ; //指向这条边加入边的编号
}
memset(head , 0 , sizeof(head) ); //使用时必须初始化!!!
for (int k = 1 ; k <= n ; k++ ) //点的边的遍历
{
for (int i = head[k] ; i != 0 ; i = e[i].next )
{ //便利以k为起点的边
printf("%d %d %d \n" ,k,e[i].to,e[i].w);
}
//当i变成0的时候,说明为空了,遍历完了!(因为head的初值为0也就是最开始的指针 )
}
这题还有个坑点,就是会WA int !!!难受啊!要将所有和权值有关的都改为long long !!!
AC代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
#define IOS ios::sync_with_stdio(false);
typedef long long ll;
const ll INF =0x3f3f3f3f3f3f3f3f;
int pot,pot2;
int n,m;
struct edge {
int to,next;
ll w;
}e[1000010],e2[1000010];
int head[1000010];
int head2[1000010];
ll dis[1000010];
ll dis2[1000010];
bool vis[1000010];
void add(int a,int b,ll c)
{
pot++;
e[pot].to = b;
e[pot].w = c;
e[pot].next = head[a];
head[a] = pot ;
}
void add2(int a,int b,ll c)
{
pot2++;
e2[pot2].to = b;
e2[pot2].w = c;
e2[pot2].next = head2[a];
head2[a] = pot2 ;
}
struct bian
{
int z;
ll w;
bool operator < (const bian &other) const
{
return w > other.w;
}
};
void djs()
{
priority_queue <bian> q;
for ( int i = 1 ;i <= n ; i++ )
dis[i] = INF;
memset(vis,0,sizeof(vis));
bian tmm;
dis[1] = 0;
tmm.z = 1;
tmm.w = dis[tmm.z];
q.push(tmm);
while(!q.empty())
{
tmm = q.top();
q.pop();
if (vis[tmm.z] == 1)
continue;
vis[tmm.z] = 1;
for (int i = head[tmm.z] ; i != 0; i =e[i].next )
{
if (dis[e[i].to] > dis[tmm.z] + e[i].w )
{
dis[e[i].to] = dis[tmm.z] + e[i].w;
bian tp ;
tp.z = e[i].to;
tp.w = dis[e[i].to];
q.push(tp);
}
}
}
for ( int i = 1 ;i <= n ; i++ )
dis2[i] = INF;
memset(vis,0,sizeof(vis));
dis2[1] = 0;
tmm.z = 1;
tmm.w = dis2[tmm.z];
q.push(tmm);
while(!q.empty())
{
tmm = q.top();
q.pop();
if (vis[tmm.z] == 1)
continue;
vis[tmm.z] = 1;
for (int i = head2[tmm.z] ; i != 0; i =e2[i].next )
{
if (dis2[e2[i].to] > dis2[tmm.z] + e2[i].w )
{
dis2[e2[i].to] = dis2[tmm.z] + e2[i].w;
bian tp ;
tp.z = e2[i].to;
tp.w = dis2[e2[i].to];
q.push(tp);
}
}
}
/* for (int i = 1 ;i <= n ; i++ )
cout<<dis[i]<<" ";
for (int i = 1 ;i <= n ; i++ )
cout<<dis2[i]<<" ";
cout<<"\n"; */
ll ans = 0;
for (int i = 1 ;i <= n ; i++ )
ans += dis[i] + dis2[i] ;
printf("%lld\n",ans);
}
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(head , 0 , sizeof(head) );
memset(head2 , 0 , sizeof(head2) );
cin>>n>>m;
for (int i = 1 ;i <= m ; i++ )
{
int a,b;
ll c;
scanf("%d%d%lld",&a,&b,&c);
add(a,b,c);
add2(b,a,c);
}
/* for (int k = 1 ; k <= n ; k++ )
{
for (int i = head[k] ; i != 0 ; i = e[i].next )
{
printf("%d %d %d \n" ,k,e[i].to,e[i].w);
}
} */
djs();
}
return 0;
}