图论之最短路习题

1.P1144 最短路计数

算法思路:邻接表存图,边权为1,spfa模板

  if(dis[to]>dis[u]+mp[u][to]) num[to]=num[u];

  else if(dis[to]==dis[u]+mp[u][to]) num[to]=(num[to]+num[u])%mod;

注意重边和自环;在运用spfa进行动态逼近松弛时,如果有一个点能被松驰,则代表有一条新的路径被发现同时整合起来

#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e6+10;const int mod=100003;int n,m,s,e;
vector<int>mp[maxn];int dis[maxn],num[maxn],vis[maxn];
void spfa(int s)
{
    memset(dis,0x3f,sizeof(dis));
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    queue<int>q;q.push(s);dis[s]=0,num[s]=1,vis[s]=1;
    while(!q.empty())
    {
        int nn=q.front();q.pop();vis[nn]=0;
        for(int i=0;i)
        {
            int t=mp[nn][i];
            if(dis[t]>dis[nn]+1) 
            {    dis[t]=dis[nn]+1,num[t]=num[nn];
                if(!vis[t]){
                    q.push(t);
                    vis[t]=1;
                }
            }
            else if(dis[t]==dis[nn]+1)
            {
                num[t]=(num[t]+num[nn])%mod;
                if(!vis[t]){
                    q.push(t);
                    vis[t]=1;
                }
            }     
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&s,&e);
        mp[s].push_back(e),mp[e].push_back(s);
    }
    spfa(1);
    for(int i=1;i<=n;i++)
        printf("%d\n",num[i]);
    return 0;
}
View Code

 2.P1119 灾后重建

 算法思路:这个题在线spfa居然wa了,卡的妙啊;注意题目中给的数据,时间是按照升序的过程进行排序,由此可在时间限制的基础上进行floy,很奇葩

也属于记忆化搜索吧,体现了floyd的动态规划的性质

#include
#include
#include
#define maxn 210
#define maxm 50010
using namespace std;
int n,m,dis[maxn][maxn],t[maxm],q,k;
int main()
{
    scanf("%d%d",&n,&m);
    memset(dis,0x3f,sizeof(dis));
    memset(t,0x3f,sizeof(t));
    for(int i=0;i)
     scanf("%d",&t[i]),
      dis[i][i]=0;
    for(int i=1;i<=m;i++)
     {
         int a,b,c;
         scanf("%d%d%d",&a,&b,&c);
         dis[a][b]=dis[b][a]=c;
     }
    scanf("%d",&q);
    for(int o=1;o<=q;o++)
     {
         int a,b,c;
         scanf("%d%d%d",&a,&b,&c);
         while(t[k]<=c)
          {
              for(int i=0;i)
               for(int j=0;j)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
              k++;
          }
        if(dis[a][b]==0x3f3f3f3f||t[a]>c||t[b]>c) printf("-1\n");
         else printf("%d\n",dis[a][b]);
     }
    return 0;
}
View Code

 3. P1608 路径统计

算法思路:用cnt数组计数就好,同1,wa1,还是不明白第一个点什莫鬼数据

#include
#include
#include
#include
#include 
using namespace std;
const int INF=0x3f3f3f3f;
int num[2100],mp[2100][2100],n,m,x,y,c;
void init(int n)
{
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            mp[i][j]=(i==j)?0:INF;
    memset(num,0,sizeof(num)); 
}
int vis[2100];int dis[2100];
void spfa(int s)
{
    fill(dis,dis+n+1,INF);
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(s);dis[s]=0;vis[s]=1;num[s]=1;
    while(!q.empty())
    {
        int now=q.front();q.pop();vis[now]=0;
        for(int i=1;i<=n;i++)
        {
            if(now==i) continue;
            if(dis[i]>dis[now]+mp[now][i])
            {
                dis[i]=dis[now]+mp[now][i];
                num[i]=num[now];
                if(!vis[i]){
                    vis[i]=1;
                    q.push(i);
                }
            }
            else if(dis[i]==dis[now]+mp[now][i])
            {
                num[i]=num[i]+num[now];
            
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);init(n);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&c);
        mp[x][y]=min(mp[x][y],c);
    }
    spfa(1);
    if(dis[n]==INF) printf("No answer");
    else printf("%d %d",dis[n],num[n]);
    return 0;
} 
View Code

 4.newcoder 小木乃伊到我家

思路:刘汝佳spfa最短路模板,结构体存路径

#include
using namespace std;
const int INF=0x3fffffff;
const int N=2e5+10;
struct node{
    int f,t,v;
};
vector<int>G[N];
vectoredge;
void add(int f,int t,int v){
    edge.push_back({f,t,v});
    edge.push_back({t,f,v});
    int m=edge.size();
    G[f].push_back(m-2);
    G[t].push_back(m-1);
}
int dis[N];int vis[N];
int n,m,from,to,v;
void spfa(int s){
    for(int i=0;i<=n;i++) vis[i]=0,dis[i]=INF;
    queue<int>q;vis[s]=1;dis[s]=0;q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();vis[u]=0;
        for(int i=0;i){
            int v=G[u][i];
            if(dis[edge[v].t]>dis[u]+edge[v].v){
                dis[edge[v].t]=dis[u]+edge[v].v;
                if(!vis[edge[v].t]){
                    q.push(edge[v].t);
                    vis[edge[v].t]=1;
                }
            }
        }
    }
}
int main(){
    
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&from,&to,&v);
            add(from,to,v);
        }
        spfa(1);
        if(dis[n]==INF) printf("qwb baka\n");
        else printf("%d\n",dis[n]);
    }
    return 0;
} 
View Code

 5.hihocoder 1093 最短路

思路:搞清楚了dijkstra和spfa的区别 博客链接 本题运用了dijkstra+优先队列

    #include
    using namespace std;
    const int N=1e5+10;
    struct edge{int to,v;};
    vectorg[N];
    const int INF=0x3f3f3f3f;
    struct node{
        int x,y;
        bool friend operator < (node a,node b){return a.y<b.y;}
        bool friend operator > (node a,node b){return a.y>b.y;}
    };
    int dis[N];
    int spfa(int s,int t){
        memset(dis,0x3f,sizeof(dis));
        dis[s]=0;
        priority_queue,greater >q;
        q.push({s,0});
        while(!q.empty()){
            node u=q.top();q.pop();
            if(dis[u.x]>u.y) continue;
            //if(vis[u.x]) continue;vis[u.x]=1;
            for(int i=0;i){
                edge v=g[u.x][i];
                if(dis[v.to]>dis[u.x]+v.v){
                    dis[v.to]=dis[u.x]+v.v;
                    q.push({v.to,dis[v.to]}); 
                }
            }
        }
        return dis[t];
    }
    int main(){
        int n,m,s,t,x,y,v;    
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&v);
            g[x].push_back({y,v});
            g[y].push_back({x,v});
        }
        int ans=spfa(s,t);
        printf("%d\n",ans);
        
        return 0;
    }
View Code

 

转载于:https://www.cnblogs.com/vainglory/p/8480534.html

你可能感兴趣的:(图论之最短路习题)