这玩意今天才知道,但感觉用处不大啊。。。
#include <bits/stdc++.h>
using namespace std;
int n,m;
struct node1
{
int d,w;
};
vector< node1 > e[30010];
struct node2
{
int v,d;
bool operator < (const node2 &y)const
{
return d > y.d;
}
};
//int point[30010],cnt,nxt[100020],des[100020],w[100020];
int a,b,c;
int h[30010],vis[30010],cnt[30010];
long long ans;
int viss[30010],dis[30010];
void add(int x,int y,int z)
{
/*cnt++;
des[cnt] = y;
nxt[cnt] = point[x];
w[cnt] = z;
point[x] = cnt;*/
e[x].push_back(node1{y,z});
}
void dij(int x)
{
//fill(dis,dis + sizeof(dis),1e9);
for (int i = 1; i <= n; i++)
{
dis[i] = 1e9;
}
memset(viss,0,sizeof(viss));
priority_queue<node2> q;
q.push(node2{x,0});
dis[x] = 0;
while(!q.empty())
{
node2 v = q.top();
q.pop();
if(viss[v.v])continue;
viss[v.v] = 1;//确定最短了
int maxx = e[v.v].size();
for (int i = 0; i < maxx; i++)
{ //if(x == 1)cout << v.v << " "<< dis[v.v] << " " <<e[v.v][i].w << " ";
if(dis[e[v.v][i].d] > dis[v.v] + e[v.v][i].w)
{
dis[e[v.v][i].d] = dis[v.v] + e[v.v][i].w;
if(!viss[e[v.v][i].d])q.push(node2{e[v.v][i].d,dis[e[v.v][i].d]});
}
}
}
}
bool spfa(int x)
{
for (int i = 0;i < 30010; i++)
{
h[i] = 1e9;
}
deque<int> q;//slf优化
q.push_back(x);
h[x] = 0,vis[x] = 1;
while(!q.empty())
{
int v = q.front();
q.pop_front();
vis[v] = 0;
int maxx = e[v].size();
for (int i = 0; i < maxx; i++)
{
if(h[v] + e[v][i].w < h[e[v][i].d])
{
h[e[v][i].d] = h[v] + e[v][i].w;
if(vis[e[v][i].d])continue;
vis[e[v][i].d] = 1;
if(h[e[v][i].d] < h[q.front()])q.push_front(e[v][i].d);
else q.push_back(e[v][i].d);
if(++cnt[e[v][i].d] >= n + 1)return false;
}
}
}
return true;
}
int main()
{
scanf("%d %d",&n,&m);
for (int i = 1; i <= m; i++)
{
scanf(" %d %d %d",&a,&b,&c);
add(a,b,c);
}
for (int i = 1; i <= n; i++)
{
add(0,i,0);//新增0号节点
}
if(!spfa(0))
{
cout << -1;
return 0;
}
for (int i = 1; i <= n; i++)
{
int maxx = e[i].size();
for (int j = 0; j < maxx; j++)
{
e[i][j].w += h[i] - h[e[i][j].d];//注意是起点减去终点
}
}
for (int i = 1; i <= n; i++)
{
ans = 0;
dij(i);
for (int j = 1; j <= n; j++)
{
//if(i == 1 && dis[j] - h[i] + h[j] > 100)cout << dis[j] - h[i] + h[j] << " ";
if(i != j && dis[j] != 1e9)ans += 1ll * j * ( dis[j] - h[i] + h[j] );
if(i != j && dis[j] == 1e9)ans += 1ll * (1e9) * j;
}
printf("%lld\n",ans);
}
return 0;
}
注意:
1.spfa判负环的是>= n + 1,因为新增了一个点,判断负环一定要在加队列之后判,松弛的时候判断好像是错的
2.还加了一个slf优化(也是今天才知道。。。)
3.一开始T了一个点,因为(dij)中"if(viss[v.v])continue"没加,加后,要注意while之前不能初始化viss[x] = 0。