【百度之星】最短路2

Time Limit: 6000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 160    Accepted Submission(s): 40
node

小 A 是社團裏的工具人,有一天他的朋友給了他一個 n 個點,m 條邊的正權連通無向圖,要他計算全部點兩兩之間的最短路。

做爲一個工具人,小 A 熟練掌握着 floyd 算法,設 w[i][j] 爲原圖中 (i,j) 之間的權值最小的邊的權值,若沒有邊則 w[i][j]=無窮大。特別地,若 i=j,則 w[i][j]=0

Floyd 的 C++ 實現以下:

```c++
for(int k=1;k<=p;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
  w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
```

當 p=n 時,該代碼就是咱們所熟知的 floyd,然而小 A 爲了讓代碼跑的更快點,因此想減小 p 的值。

令 Di,j 爲最小的非負整數 x,知足當 p=x 時,點 i 與點 j 之間的最短路被正確計算了。

如今你須要求 ni=1nj=1Di,j,雖然答案不會很大,但爲了顯得本題像個計數題,你仍是須要將答案對 998244353 取模後輸出。
ios

 

Input
第一行一個正整數  T(T30) 表示數據組數

對於每組數據:

第一行兩個正整數 n,m(1n1000,m2000),表示點數和邊數。

保證最多隻有 5 組數據知足 max(n,m)>200 

接下來 m 行,每行三個正整數 u,v,w 描述一條邊權爲 w 的邊 (u,v),其中 1w109


Output
輸出  T 行,第 i 行一個非負整數表示第 i 組數據的答案
 
Sample Input
1 4 4 1 2 1 2 3 1 3 4 1 4 1 1
 
Sample Output
6

題解:跑堆優化的 Dijkstra(修改過),每一個點跑一遍,而後邊跑邊記錄D[i][j]。具體操做看代碼。c++

 

#pragma comment(linker, "/STACK:1024000000,1024000000")
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const long long mod = 998244353;
const int maxn = 2e3;
 
int D[maxn][maxn];
int ans;
int n,m;
const ll INF=3e13;
const int MAXN=5010;
 
struct qnode
{
    int v;
    ll c;
    qnode(int _v=0,ll _c=0):v(_v),c(_c){}
    bool operator <(const qnode &r)const
    {
        return c>r.c;
    }
};
struct Edge
{
    int v;
    ll cost;
    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
 
vector<Edge>E[MAXN];
bool vis[MAXN];
ll dist[MAXN];
void Dijkstra(int n,int start)//點的編號從1開始
{
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++)dist[i]=INF;
    priority_queue<qnode>que;
    while(!que.empty())que.pop();
    dist[start]=0;
    for(int i=0;i<E[start].size();i++)
    {
        que.push(qnode(E[start][i].v,E[start][i].cost));
        dist[E[start][i].v]=min(E[start][i].cost,dist[E[start][i].v]);
    }
    qnode tmp;
    while(!que.empty())
    {
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u]) continue;
        vis[u]=true;
        for(int i=0;i<E[u].size();i++)
        {
            int v=E[u][i].v;
            ll cost=E[u][i].cost;
            if(dist[v]>dist[u]+cost)
            {
                dist[v]=dist[u]+cost;
                D[start][v]=max(D[start][u],u);
                que.push(qnode(v,dist[v]));
            }
            else if(dist[v]==dist[u]+cost)
            {
                D[start][v]=min(max(u,D[start][u]),D[start][v]);
            }
        }
    }
}
 
void addedge(int u,int v,ll w)
{
    E[u].push_back(Edge(v,w));
}
 
void init()
{
    ans=0;
    for(int i=1;i<=n;i++)
    {
        E[i].clear();
        for(int j=1;j<=n;j++)
        {
            D[i][j]=0;
        }
    }
}
 
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        init();
        for(int i=0;i<m;i++)
        {
            int u,v;
            ll W;
            scanf("%d %d %lld",&u,&v,&W);
            addedge(u,v,W);
            addedge(v,u,W);
        }
        for(int i=1;i<=n;i++)
            Dijkstra(n,i);
 
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                //printf("%d ",D[j][i]);
                ans+=D[i][j];
                ans%=mod;
            }
            //printf("\n");
        }
        printf("%d\n",ans);
    }
    return 0;
}
 
 
 
 
 
 
相關文章
相關標籤/搜索