1. 程式人生 > >1003 Emergency (25 分)(求最短路徑)

1003 Emergency (25 分)(求最短路徑)

給出N個城市,m條無向邊。每個城市中都有一定數目的救援小組,所有邊的邊權已知。現在給出起點和終點,求從起點到終點的最短路徑條數及最短經上的救緩小組數目只和。如果有多條最短路徑,則輸出數目只和最大的

Dijkstra 做法

#include<bits/stdc++.h>
using namespace std;
int n,m,s,u;
const int N=1000;
const int inf=0x3f3f3f3f;
int mp[N][N];
int dis[N];
bool vis[N];
int value[N];
int num[N];
int w[N];
void Dijkstra()
{
    fill(vis,vis
+N,false); fill(dis,dis+N,inf); fill(w,w+N,0); fill(num,num+N,0); num[s]=1;//賦值 w[s]=value[s];//賦值 for(int i=0;i<n;i++) dis[i]=mp[s][i]; dis[s]=0; for(int i=0;i<n-1;i++){ int u=-1; int minn=inf; for(int j=0;j<n;j++){ if(!vis[j]&&dis[j]<minn){ u
=j; minn=dis[j]; } } if(u==-1) return; vis[u]=true; for(int j=0;j<n;j++){ if(!vis[j]&&dis[u]+mp[u][j]<=dis[j]){ if(mp[u][j]+dis[u]<dis[j]){ dis[j]=mp[u][j]+dis[u]; num[j]
=num[u]; w[j]=w[u]+value[j]; } else{ num[j]+=num[u]; if(w[u]+value[j]>w[j]){ w[j]=w[u]+value[j]; } } } } } } int main() { scanf("%d %d %d %d",&n,&m,&s,&u); for(int i=0;i<n;i++) scanf("%d",&value[i]); memset(mp,inf,sizeof(mp)); while(m--){ int a,b,c; scanf("%d %d %d",&a,&b,&c); mp[a][b]=mp[b][a]=c; } Dijkstra(); printf("%d %d",num[u],w[u]); return 0; }

 

spfa做法

#include<bits/stdc++.h>

using namespace std;
int n,m,s,v;
struct node
{
    int to;
    int dis;
    node(int _to=0,int _dis=0):to(_to),dis(_dis){}
};
const int N=1010;
int dis[N];
bool vis[N];
int w[N];
int num[N];
int value[N];
vector<node>mp[N];
set<int>st[N];
const int inf=0x3f3f3f3f;
void spfa()
{
    fill(dis,dis+N,inf);
    fill(vis,vis+N,false);
    fill(w,w+N,0);
    w[s]=value[s];
    num[s]=1;
    queue<int>Q;
    Q.push(s);
    vis[s]=true;
    dis[s]=0;
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        vis[u]=false;
        for(int i=0;i<mp[u].size();i++){
            int to=mp[u][i].to;
            int diss=mp[u][i].dis;
            if(diss+dis[u]<dis[to]){
                dis[to]=diss+dis[u];
                w[to]=w[u]+value[to];
                num[to]=num[u];
                st[to].clear();
                st[to].insert(u);
                if(!vis[to]){
                    Q.push(to);
                    vis[to]=true;
                }
            }
            else if(diss+dis[u]==dis[to]){
                if(w[to]<w[u]+value[to]){
                    w[to]=w[u]+value[to];               
                }
                st[to].insert(u);
                num[to]=0;//因為spfa會重複到一個點 所以可能重複的邊
                for(set<int>::iterator it=st[to].begin();it!=st[to].end();++it){
                    num[to]+=num[*it];
                }
                if(!vis[to]){
                    Q.push(to);
                    vis[to]=true;
                }
            }
        }
    }
}
int main()
{
    scanf("%d %d %d %d",&n,&m,&s,&v);
    for(int i=0;i<n;i++) scanf("%d",&value[i]);
    for(int i=0;i<n;i++) mp[i].clear();
    while(m--){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        mp[a].push_back(node(b,c));
        mp[b].push_back(node(a,c));
    }
    spfa();
    printf("%d %d\n",num[v],w[v]);

    return 0;
}