[团体程序设计天梯赛](L2-001)紧急救援 ---- SPFA +DFS

题目传送门

  • zz操作:一开始把最短路径条数理解成了最短的路径有几条路,wa到底,特此记录一下
  • 仔细一看才是最短路径一共有几条,样例成功骗了我 23333

解题思路: SPFA跑出最短路,prev数组记录路径,llen数组记录到达每个结点的累加人数。
最后dfs跑一下,找出所有的最短路即可
AC代码:

#include 
using namespace std;

#define IO ios_base::sync_with_stdio(0),cin.tie(0)
#define fin freopen("in.txt","r",stdin)

typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f;
const double PI = 4*atan(1.0);

int n,m,s,d;
struct node
{
    int to;
    int nex;
    int w;
    int len;
}edge[505*505];
bool vis[maxn];
int head[maxn];
int cnt = 0;
int dist[maxn];
void addedge(int u,int v,int w)
{
    edge[cnt].to = v;
    edge[cnt].w = w;
    edge[cnt].nex = head[u];
    edge[cnt].len = 1;
    head[u] = cnt;
    cnt++; 
}
int llen[maxn];
int pnum[maxn];
int prevz[maxn];
int step[maxn];
int tot;
void spfa()
{
    queue<int> q;
    vis[s] = 0;
    q.push(s);
    memset(dist,INF,sizeof(dist));
    dist[s] = 0;
    llen[s] = pnum[s];
    prevz[s] = -1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int i = head[u];~i;i = edge[i].nex){
            int v = edge[i].to;
            if(dist[v] > dist[u]+edge[i].w || (dist[v] == dist[u]+edge[i].w && llen[v]<llen[u]+pnum[v])){
                dist[v] = dist[u]+edge[i].w;
                llen[v] = llen[u]+pnum[v];
                prevz[v] = u;
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
}
int res = 0;
void dfs(int p)
{
	if(p == d){
		res++;
		return;
	}
	for(int i = head[p];~i;i=edge[i].nex){
		int v = edge[i].to;
		if(!vis[v] && dist[v] == dist[p]+edge[i].w){
			vis[v] = true;
			dfs(v);
			vis[v] = false;
		}
	}
}
int main()
{
//  	fin;
    IO;
    memset(head,-1,sizeof(head));
    cin>>n>>m>>s>>d;
    for(int i=0;i<n;i++) cin>>pnum[i];
    for(int i=1;i<=m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        addedge(u,v,w);
        addedge(v,u,w);
    }
    spfa();
    int tmp = prevz[d];
    step[tot++] = d;
    while(tmp!=-1){
        step[tot++] = tmp;
        tmp = prevz[tmp];
    }
    memset(vis,0,sizeof(vis));
    dfs(s);
    cout<<res<<" "<<llen[d]<<endl;
    for(int i=tot-1;i>=0;i--){
        if(i == tot-1) cout<<step[i];
        else cout<<" "<<step[i];
    }
    return 0;
}

你可能感兴趣的:(【图论】)