至少得知道floyd的最初形式,dp[k][i][j],只经过前k个点,i到j的最短路。
所以题目就是问你,任意两点间的最短路,经过的最大编号的点最小是多少,还不含两个端点。
魔改一下dijkstra就行了,每个点跑一次。先比较长度,长度相同比较下最大编号谁的更小。每个点存的经过最大编号并不包含这个点本身。记得特判下起点终点直连的情况。
1 #include <cstdio>
2 #include <queue>
3 using namespace std;
4 typedef long long ll;
5 const int mo = 998244353,MAXN = 1010,MAXM = 4010;
6 const ll inf = 1e14;
7 struct pot
8 {
9 int x,maxn;
10 ll dis;
11 pot (int _x = 0,ll _dis = 0,int _maxn = 0) : x(_x),dis(_dis),maxn(_maxn) {}
12 friend bool operator < (pot a,pot b)
13 {
14 if (a.dis != b.dis)
15 return a.dis > b.dis;
16 return a.maxn > b.maxn;
17 }
18 };
19 struct dat
20 {
21 int maxn;
22 ll dis;
23 dat (ll _dis = 0,int _maxn = 0) : dis(_dis),maxn(_maxn) {}
24 friend bool operator < (dat a,dat b)
25 {
26 if (a.dis != b.dis)
27 return a.dis > b.dis;
28 return a.maxn > b.maxn;
29 }
30 };
31 priority_queue <pot> que;
32 dat dis[MAXN];
33 int head[MAXN],to[MAXM],nxt[MAXM],val[MAXM];
34 int T,n,m,cnt,ans;
35 bool vis[MAXN];
36 void add(int x,int y,int v)
37 {
38 nxt[++cnt] = head[x];
39 to[cnt] = y;
40 head[x] = cnt;
41 val[cnt] = v;
42 }
43 void dijkstra(int s)
44 {
45 for (int i = 1;i <= n;i++)
46 {
47 dis[i] = dat(inf,0);
48 vis[i] = false;
49 }
50 que.push(pot(s,0,0));
51 dis[s] = dat(0,0);
52 while(que.empty() == false)
53 {
54 pot now = que.top();
55 que.pop();
56 if(vis[now.x] == true)
57 continue;
58 vis[now.x] = true;
59 for(int i = head[now.x]; i; i = nxt[i])
60 {
61 if (now.x != s)
62 {
63 if(dis[to[i]].dis > dis[now.x].dis + val[i] || (dis[to[i]].dis == dis[now.x].dis + val[i]) && (max(dis[now.x].maxn,now.x) < dis[to[i]].maxn))
64 {
65 dis[to[i]].dis = dis[now.x].dis + val[i];
66 dis[to[i]].maxn = max(dis[now.x].maxn,now.x);
67 que.push(pot(to[i],dis[to[i]].dis,dis[to[i]].maxn));
68 }
69 }else
70 {
71 if(dis[to[i]].dis >= dis[now.x].dis + val[i])
72 {
73 dis[to[i]].dis = dis[now.x].dis + val[i];
74 dis[to[i]].maxn = 0;
75 que.push(pot(to[i],dis[to[i]].dis,dis[to[i]].maxn));
76 }
77 }
78 }
79 }
80 }
81 int main()
82 {
83 for (scanf("%d",&T);T != 0;T--)
84 {
85 for (int i = 1;i <= cnt;i++)
86 nxt[i] = 0;
87 for (int i = 1;i <= n;i++)
88 head[i] = 0;
89 cnt = ans = 0;
90 scanf("%d%d",&n,&m);
91 int tx,ty,tv;
92 for (int i = 1;i <= m;i++)
93 {
94 scanf("%d%d%d",&tx,&ty,&tv);
95 add(tx,ty,tv);
96 add(ty,tx,tv);
97 }
98 for (int i = 1;i <= n;i++)
99 {
100 dijkstra(i);
101 for (int j = 1;j <= n;j++)
102 ans = ((ll)ans + dis[j].maxn) % mo;
103 }
104 printf("%d\n",ans);
105 }
106 return 0;
107 }