zoukankan      html  css  js  c++  java
  • 2018-南京网络赛icpc-L题(分层最短路)

    题意:给你n个点,m条边的有向带权图,然后你每次可以选<=k条边的边权变成0,问你1到n的最短路;

    解题思路:这道题基本上就是原题了呀,bzoj2763(无向图),解法就是拆点跑分层的最短路,比如这道题,你用了一次变为0,就相当于进入了下一个层次;

    我们把每个点都拆成k个层次点,每个相同层次的点按输入的边权连接,每个点可以向它能连接到的点的下一个层次连接一条边权为0的边;

    意思就是:输入x到y权值为w的边

        for(int i=1;i<=m;i++)
            {
                scanf("%lld%lld%lld",&x,&y,&w);
                for(int j=0;j<=k;j++)
                {
                    add(x+j*n,y+j*n,w);同一层次的点;
                    if(j!=k)
                    add(x+j*n,y+(j+1)*n,0);不同层次的点,可以向它能连接的下一个层次连一个边权为0;
                }
            }
    完整代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<stack>
    #define ll long long
    using namespace std;
    const int maxm=3000500;
    const ll inf=0x7f7f7f7f;
    const int maxn=100500;
    struct node
    {
    ll num;
    ll dist;
    node(ll _num,ll _dist):num(_num),dist(_dist){}
    friend bool operator<(node a,node b)
    {
    return a.dist>b.dist;
    }
    };
    struct Edge
    {
    ll next;
    ll to;
    ll w;
    }edge[maxm*2];
    int head[maxm];
    ll dist[maxm];
    int cnt;
    int n,m,k;
    void add(ll u,ll v,ll w)
    {
    edge[cnt].next=head[u];
    edge[cnt].to=v;
    edge[cnt].w=w;
    head[u]=cnt++;
    }
    void dij(int u)
    {
    priority_queue<node>q;
    memset(dist,inf,sizeof(dist));
    dist[u]=0;
    q.push(node(u,dist[u]));
    while(!q.empty())
    {
    node now=q.top();
    //cout<<now.num<<" "<<now.dist<<endl;
    q.pop();
    int x=now.num;
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
    int v=edge[i].to;
    if(dist[v]>dist[x]+edge[i].w)
    {
    dist[v]=dist[x]+edge[i].w;
    q.push(node(v,dist[v]));
    }
    }
    }
    }
    int main()
    {
    int tt;
    ll x,y,w;
    scanf("%d",&tt);
    while(tt--)
    {
    memset(head,-1,sizeof(head));cnt=0;
    scanf("%d%d%d",&n,&m,&k);
    if(k>=m)
    {
    printf("0
    ");
    continue;
    }
    for(int i=1;i<=m;i++)
    {
    scanf("%lld%lld%lld",&x,&y,&w);
    for(int j=0;j<=k;j++)
    {
    add(x+j*n,y+j*n,w);
    if(j!=k)
    add(x+j*n,y+(j+1)*n,0);
    }
    }
    dij(1);
    ll ans=inf;
    for(int i=0;i<=k;i++)
    {
    ans=min(ans,dist[n+i*n]);
    }
    printf("%lld
    ",ans);
    }
    }
  • 相关阅读:
    matlab软件-了解
    C# 自定义异常demo
    C#二进制对象copy
    asp.net 缓存依赖demo
    权限管理细粒度问题
    三层架构中的异常处理二
    如何解决复杂问题——结构化思维方式
    入职新公司如何熟悉项目
    专业工具使用与复杂大型项目设计管理
    十分钟学会 tmux
  • 原文地址:https://www.cnblogs.com/huangdao/p/9571652.html
Copyright © 2011-2022 走看看