vijos1027-spfa&关键路径-休息中的阿呆

原创 2018年04月15日 19:34:17

https://vijos.org/p/1027
给定一个有向图,n个顶点,m个边。每个边有时间作为边权,问从1到n,最少花费多少时间可以把真个图都过一遍(把每个顶点都过一遍)。并且输出所有可能经过的点(用最少时间t走的所有可能经过的点)
思路:spfa改下方向就好了,把d数组改成无穷小,关键路径的输出我是用一个vector存的。当进行松弛操作的时候,如果成功就改。
两种输出关键路径的方法。
坑点:题目中说所有可能的点,意思是如果有两条同样长的点,那么要一起输出,最好的方法是erase和unique了。
我开始以为只要进行过松弛操作,只要把进行过松驰过操作的所有点(to和u都记录,)通过去重就可以得到答案,但是其实不然,因为最长(短)路一定松驰,但是松驰不一定是最长(短)路
见下图,红色的区域发生过松弛操作,但是一定不可能在最短路中
这里写图片描述

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+4;
vector<pair<int,int> >g[maxn];
int d[maxn];
bool vis[maxn];
vector<int>kk[maxn];
int m;
int mp[maxn][maxn];
vector<int>w;
void dfs(int s,vector<int>q,int v){
     if(!s){
        for(int i=0;i<q.size();i++){
            w.push_back(q[i]);
        }
        return;
     }
     for(int i=1;i<=m;i++){
         vector<int>p(q.begin(),q.end());
         if(d[i]==(s-mp[v][i])&&mp[v][i]){
            p.push_back(i);
            dfs(d[i],p,i);
         }
     }
     return;
}
void spfa(){
    queue<int>q;
    memset(vis,false,sizeof(vis));
    memset(d,-0x3f3f3f3f,sizeof(d));
    for(int i=0;i<maxn;i++)kk[i].clear();
    q.push(1);
    vis[1]=true;
    d[1]=0;
    while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=false;
            for(int i=0;i<g[u].size();i++){
                int to=g[u][i].first;
                int cost=g[u][i].second;
                if(d[to]<d[u]+cost){
                     d[to]=d[u]+cost;
                     if(!vis[to]){
                        q.push(to);
                        vis[to]=true;
                     }
                }
                else if(d[to]==d[u]+cost){
                     for(int x=0;x<kk[u].size();x++){
                        kk[to].push_back(kk[u][x]);
                     }
                     kk[to].push_back(u);
                }
            }
    }
    int s=d[m+1];
    printf("%d\n",s);
    vector<int>ss;ss.clear();
    w.clear();
    dfs(s,ss,m+1);
    w.push_back(m+1);
    sort(w.begin(),w.end());
    w.erase(unique(w.begin(),w.end()),w.end());
    for(int i=0;i<w.size();i++){
        if(!i)
            printf("%d",w[i]);
        else
            printf(" %d",w[i]);
    }
    printf("\n");
}
int main()
{   int n,a,b,c;
    scanf("%d%d",&m,&n);
    for(int i=0;i<n;i++){
         scanf("%d%d%d",&a,&b,&c);
         g[a].push_back(make_pair(b,c));
         mp[a][b]=c;
         mp[b][a]=c;
    }
    spfa();
    return 0;
}

第一个代码还是有点麻烦,得用邻接矩阵(如果存图也用邻接矩阵就没那么麻烦了)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+4;
vector<pair<int,int> >g[maxn];
int d[maxn];
bool vis[maxn];
vector<int>kk[maxn];
int m;
void spfa(){
    queue<int>q;
    memset(vis,false,sizeof(vis));
    memset(d,-0x3f3f3f3f,sizeof(d));
    for(int i=0;i<maxn;i++)kk[i].clear();
    q.push(1);
    vis[1]=true;
    d[1]=0;
    while(!q.empty()){
          int u=q.front();
            q.pop();
            vis[u]=false;
            for(int i=0;i<g[u].size();i++){
                int to=g[u][i].first;
                int cost=g[u][i].second;
                if(d[to]<d[u]+cost){
                     d[to]=d[u]+cost;
                     kk[to].clear();
                     for(int x=0;x<kk[u].size();x++){
                        kk[to].push_back(kk[u][x]);
                     }
                     kk[to].push_back(u);
                     if(!vis[to]){
                        q.push(to);
                        vis[to]=true;
                     }
                }
                else if(d[to]==d[u]+cost){
                     for(int x=0;x<kk[u].size();x++){
                        kk[to].push_back(kk[u][x]);
                     }
                     kk[to].push_back(u);
                }
            }
    }
      //for(int i=1;i<=m+1;i++)
          //printf("**%d\n",d[i]);
    sort(kk[m+1].begin(),kk[m+1].end());
    kk[m+1].erase(unique(kk[m+1].begin(),kk[m+1].end()),kk[m+1].end());
    printf("%d\n",d[m+1]);
    for(int i=0;i<kk[m+1].size();i++){
        if(!i)
              printf("%d",kk[m+1][0]);
        else
              printf(" %d",kk[m+1][i]);
    }
    printf(" %d",m+1);
    printf("\n");
}
int main()
{   int n,a,b,c;
    scanf("%d%d",&m,&n);
    for(int i=0;i<n;i++){
         scanf("%d%d%d",&a,&b,&c);
         g[a].push_back(make_pair(b,c));
    }
    //puts("!!!");
    spfa();
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35781950/article/details/79952182

巧算星期几

 巧算星期几 基姆。拉尔森基姆拥有计算机学科的博士学位。他对数据库,算法和数据结构有着浓厚的兴趣。他的联系地址是            (原文为丹麦文--译者注) 31,DK-5270,Odense ...
  • ycrao
  • ycrao
  • 2000-11-24 16:32:00
  • 8269

EDGE浏览器配合阿呆喵设置广告过滤

阿呆喵的旧版本有一个选项是一键支持EDGE,不过新版本没有了这个选项。 虽然EDGE也有了可用的广告过滤插件,但是无论是内存占用和过滤效果都差强人意。想要实现过滤,可以借助广告过滤软件——阿呆喵。 阿...
  • sdujava2011
  • sdujava2011
  • 2016-12-13 14:51:48
  • 2298

阿呆喵 for Mac

  • 2015年09月05日 15:37
  • 2.25MB
  • 下载

云存储+阿呆系列.pdf

  • 2011年08月18日 17:23
  • 2.03MB
  • 下载

关键路径的选取

这是一篇我的心得,写verilog的心得,啊,对于学习verilog设计FPGA的同学一定会有帮助的啊!     本人就例子来教大家怎样提取关键路径:     先解释一下什么叫关键路径     所谓关...
  • zhongrg
  • zhongrg
  • 2007-10-22 22:08:00
  • 2001

数字电路中关键路径的选取

所谓关键路径就是,在电路中频繁调用,而且延迟过长,或者产生意外的几率比较大的线路。 怎样提取关键路径: 1:组合电路中的关键路径提取:   q=a&b&c|d&e&b;   因为b的传输要两级...
  • xiangyuqxq
  • xiangyuqxq
  • 2012-02-17 13:21:15
  • 3849

项目管理入门(4)——基本原则之关键路径

翻译来源:A Project Management Primeror “a guide to making projects work (v2.0)”by Nick Jenkins基本原则之关键路径 ...
  • donhao
  • donhao
  • 2010-09-04 15:58:00
  • 863

邻接表关键路径

邻接表关键路径
  • lianbanguomao
  • lianbanguomao
  • 2016-04-25 17:30:33
  • 335

软件开发的过程中关键路径问题

   任何项目的实施均需要划分成若干阶段进行,每个阶段又可以分成若干步骤。为了提高整个项目的进度通常方式会采用多组人并行实施的策略,但由于这些步骤之间在时间上存在先后制约关系(例如:建筑施工前需要先购...
  • yourdream
  • yourdream
  • 2005-01-08 13:07:00
  • 1304

AOE网络与关键路径(一)

1、与AOV网络密切相关的是AOE网络。如果在DAG中用有向边表示一个工程的各项活动,用有向边上的权值表示活动的持续时间,用顶点表示事件,则这种有向图叫做用边表示活动的网络(Activity On...
  • u012904198
  • u012904198
  • 2014-04-07 00:24:12
  • 3810
收藏助手
不良信息举报
您举报文章:vijos1027-spfa&关键路径-休息中的阿呆
举报原因:
原因补充:

(最多只允许输入30个字)