hdu4725(The Shortest Path in Nya Graph)最短路

这道题数据范围比较大,如果暴力建图肯定T了,需要一点小技巧,本人太渣,看了大牛的博客才懂的。
kuang神
有两种思路

思路1,拆点

增加2n个点,也就是每层变成两个点。
n+2* i-1->n+2 *(i+1) ,路权为c;即指向上一层
n+2*(i+1)-1->n+2 * i ,路权为c;即指向下一层

如果i属于u层,

i->n+2*u-1,路权为零,入层
n+2*u->i,路权为零,出层
再加上m条有向边,建图完成,接着就是最短路,dijkst+堆优化和spfa都可以。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=1010010;
const int INF=0x3f3f3f3f;
int d[MAXN],tot,hd[MAXN];
bool vs[MAXN];
struct _Edge
{
    int to,c,next;
    bool operator < (const _Edge &a) const{
        return c>a.c;
    }
}edge[2*MAXN];
inline void addedge(int u,int v,int c)
{
    edge[tot].to=v;
    edge[tot].c=c;
    edge[tot].next=hd[u];
    hd[u]=tot++;
}
void Dijkst(int beg,int n)
{
    struct _Edge tmp;
    ms(vs);
    for(int i=1;i<=n;i++) d[i]=INF;
    priority_queue <struct _Edge> q;
    while(!q.empty()) q.pop();
    tmp.to=beg,tmp.c=0;
    d[beg]=0;
    q.push(tmp);
    while(!q.empty()){
        tmp=q.top();
        q.pop();
        int u=tmp.to;
        if(vs[u]) continue;
        vs[u]=true;
        for(int i=hd[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(!vs[v]&&d[v]>d[u]+edge[i].c)
                {tmp.c=d[v]=d[u]+edge[i].c;
                    tmp.to=v;
                    q.push(tmp);
                }
        }
    }
}
int main(int argc, char const *argv[])
{
    int t,ti=0;
    cin>>t;
    while(++ti<=t){
        int n,m,CT;
        msc(hd);
        tot=0;
        scanf("%d %d %d",&n,&m,&CT);
        for(int i=1;i<=n;i++) {
            int l;
            scanf("%d",&l);
            addedge(i,n+2*l-1,0);
            addedge(n+2*l,i,0);
            addedge(n+2*(i+1)-1,n+2*i,CT);
            addedge(n+2*i-1,n+2*(i+1),CT);
        }
        while(m--){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            addedge(a,b,c);
            addedge(b,a,c);
        }
        Dijkst(1,3*n);
        printf("Case #%d: ",ti );
        if(d[n]==INF) puts("-1");
        else printf("%d\n",d[n] );
    }
    return 0;
}

思路2.点更新层更新

但是,这需要姿势,否则时间复杂度就上去了。
像边一样,建一个邻接表,保存每一层的信息。然后更新每个点的时候也更新一次层上所有的点。
代码?我没写=.=|||

你可能感兴趣的:(acm之路,图论初步,思路++)