kuangbin带我飞 专题四 最短路

来源:互联网 发布:游戏心理学 知乎 编辑:程序博客网 时间:2024/05/15 23:52

poj 2387 

全裸的最短路,随便什么算法都能过

Poj 2253

这题可以用最小生成树来做,kruskal搞一下,如果1-2连同,此时的边就是青蛙跳的最大距离

while(scanf("%d",&n)&&n){        kase++;        int xcount=0;        for(int i=1;i<=n;i++) pre[i]=i;        for(int i=1;i<=n;i++){            scanf("%d%d",&a[i],&b[i]);            for(int j=1;j<i;j++){                p[xcount].from=j;                p[xcount].to=i;                p[xcount++].cost=sqrt(double((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j])));            }        }        sort(p,p+xcount,cmp);        for(int i=0;i<xcount;i++){            Union(p[i].from,p[i].to);            if(Find(1)==Find(2)){                printf("Scenario #%d\nFrog Distance = %.3lf\n\n",kase,p[i].cost);                break;            }        }    }

poj 1797

这个题是求1-n的路中,最小边最大的一条路,可以用spfa变化下求。

dis[k]=max(dis[k],min(dis[x],edge[x][k]));

void spfa(int u){    queue<int> q;    q.push(u);    vis[u]=1;    dis[u]=INF;    while(!q.empty()){        int x=q.front();        q.pop();        vis[x]=0;        for(int i=0;i<v[x].size();i++){            int k=v[x][i];            if(dis[k]<min(dis[x],edge[x][k])){                dis[k]=min(dis[x],edge[x][k]);                if(!vis[k]){                    vis[k]=1;                    q.push(k);                }            }        }    }}

poj 3268

题意:给你m个有向边,n个牛先从自己家去x点,再回去,问哪个牛走的最长

题解:把给的有向边正着存一份,以x为源点求最短路,可以得到每个牛回家的距离。

再把所有有向边都倒过来存一遍,以x为源点求最短路,得到的是每个牛去的时候的距离。

想加找最大即可,两次spfa的事。


poj3259

题意:这题难点就在于读题。有m条无向的路,还有w条有向的路(虫洞),A one way path from S to E that also moves the traveler back T seconds.意思是这条有向边的权值是负的,然后要求的是FJ能否回到起点,意思就是说有没有负环,如果有负环的话,他会一直在那个负环里转,因为权值每次都变小了。

题解:用spfa(bellman-ford)求负环即可

vector<int> v[505];int edge[505][505];int dis[505];int vis[505];int xcount[505];int n,m,w;void spfa(int u){    queue<int> q;    q.push(u);    vis[u]=1;    dis[u]=0;    xcount[u]++;    while(!q.empty()){        int x=q.front();        q.pop();        vis[x]=0;        for(int i=0;i<v[x].size();i++){            int k=v[x][i];            if(dis[k]>dis[x]+edge[x][k]){                dis[k]=dis[x]+edge[x][k];                if(!vis[k]){                    vis[k]=1;                    q.push(k);                    xcount[k]++;                    if(xcount[k]>n){                        printf("YES\n");                        return;                    }                }            }        }    }    printf("NO\n");}

POJ 1502

题意:这题又是英语来卡人,是说从1到各个点的最短路中的最大值,说到这里就是个水题了,然而看懂题目才是最难的。


poj 3660 

题意:这题是给你m个有向边的关系,还有个确定有多少个牛的位置确定了

题解:Floyd暴力一遍,把所有有向边的关系都确定了,然后枚举每个牛,看他的入度出度之和是否为n-1

for(int k=1;k<=n;k++){        for(int i=1;i<=n;i++){            for(int j=1;j<=n;j++){                if(edge[i][k]&&edge[k][j]) edge[i][j]=1;            }        }    }    int ans=0;    for(int i=1;i<=n;i++){        int flag=0;        for(int j=1;j<=n;j++){            if(i==j) continue;            if(!(edge[i][j]||edge[j][i])) flag=1;        }        if(!flag) ans++;    }    printf("%d\n",ans);

poj 1511

这题就是个很显然的最短路,题目辣么长,然而难点在于数据量大!!!100w

题解:可以用dijkstra的堆优化和spfa来做。(刚学堆优化写的挫)

#include <iostream>#include <cstdio>#include <cctype>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <sstream>#include <stack>using namespace std;#define MAX 1000000+5#define MAXN 100000+5typedef long long LL;typedef unsigned long long ull;const double pi=3.141592653589793;const int INF=0x3f3f3f3f;const int INFF=1e9;const double inf=1e18;const double eps=1e-10;const int mod=1000000007;const int prime=999983;struct edge{    int v,cost;    edge(){}    edge(int _v,int _cost):v(_v),cost(_cost){}};struct edge2{    int u,v,w;    edge2(){}    edge2(int _u,int _v,int _w):u(_u),v(_v),w(_w){}}a[MAX];struct node{    int id,val;    node(){}    node(int _id,int _v):id(_id),val(_v){}    bool operator <(const node &a)const{                //重载<,使优先队列队首始终是val最小的元素        return val>a.val;    }}x,y;vector<edge> v[MAX];int vis[MAX];int dis[MAX];int n,m;LL dijkstra(int s){    priority_queue<node> q;    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    x.id=s;    x.val=0;    dis[s]=0;    q.push(x);    while(!q.empty()){        x=q.top();        q.pop();        int num=x.id;        if(vis[num]) continue;        vis[num]=1;        for(int i=0;i<v[num].size();i++){            int to=v[num][i].v;            int cost=v[num][i].cost;            if(!vis[to]&&dis[to]>dis[num]+cost){                dis[to]=dis[num]+cost;                y.id=to;                y.val=dis[to];                q.push(y);            }        }    }    LL sum=0;    for(int i=1;i<=n;i++) sum+=dis[i];    return sum;}int main(){    int t;    scanf("%d",&t);    while(t--){        LL ans=0;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++) v[i].clear();        for(int i=1;i<=m;i++){            int u,vv,w;            scanf("%d%d%d",&u,&vv,&w);            a[i]=edge2(u,vv,w);            v[u].push_back(edge(vv,w));        }        ans+=dijkstra(1);        for(int i=1;i<=n;i++) v[i].clear();        for(int i=1;i<=m;i++){            int u = a[i].u;            int vv = a[i].v;            int w = a[i].w;            v[vv].push_back(edge(u,w));        }        ans+=dijkstra(1);        printf("%lld\n",ans);    }    return 0;}

下面是spfa的算法:时间复杂度和dijkstra的差不多(我以前用了LL 果断T了10次+)存结构体这种方法非常好,get

#include <iostream>#include <cstdio>#include <cctype>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <sstream>#include <stack>using namespace std;#define MAX 1000000+5#define MAXN 100000+5typedef long long LL;typedef unsigned long long ull;const double pi=3.141592653589793;const int INF=0x3f3f3f3f;const int INFF=1e9;const double inf=1e18;const double eps=1e-10;const int mod=1000000007;const int prime=999983;struct edge{    int v,cost;    edge(){}    edge(int _v,int _c):v(_v),cost(_c){}};struct edge2{    int u,v,w;    edge2(){}    edge2(int _u,int _v,int _w):u(_u),v(_v),w(_w){}}a[MAX];vector<edge> v[MAX];int dis[MAX];int vis[MAX];int n,m;LL spfa(int s){    queue<int> q;    memset(dis,INF,sizeof(dis));    memset(vis,0,sizeof(vis));    dis[s]=0;    vis[s]=1;    q.push(s);    while(!q.empty()){        int x=q.front();        q.pop();        vis[x]=0;        for(int i=0;i<v[x].size();i++){            int k=v[x][i].v;            int cost=v[x][i].cost;            if(dis[k]>dis[x]+cost){                dis[k]=dis[x]+cost;                if(!vis[k]){                    vis[k]=1;                    q.push(k);                }            }        }    }    LL sum=0;    for(int i=1;i<=n;i++) sum+=dis[i];    return sum;}int main(){    int t;    scanf("%d",&t);    while(t--){        LL ans=0;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++) v[i].clear();        for(int i=1;i<=m;i++){            int u,vv,w;            scanf("%d%d%d",&u,&vv,&w);            a[i]=edge2(u,vv,w);            v[u].push_back(edge(vv,w));        }        ans+=spfa(1);        for(int i=1;i<=n;i++) v[i].clear();        for(int i=1;i<=m;i++){            int u = a[i].u;            int vv = a[i].v;            int w = a[i].w;            v[vv].push_back(edge(u,w));        }        ans+=spfa(1);        printf("%lld\n",ans);    }    return 0;}

poj 3159

题意:给你a,b,c三个数意思是a认为b不能比他多c个糖,p[b]-p[a]<=c,即为 p[b]<=p[a]+c,这就是显然的最短路,详见差分约束系统http://blog.csdn.net/xuezhongfenfei/article/details/8685313

题解:这题就是数据量大,用vector建图过不了,用dijkstra+heap+前向星可以过,spfa+stack也轻松掠过。答案就是求p[n]-p[1]的最大值,即dis[n](感觉我差分也没全搞懂,改天还得学学)(dijkstra和spfa复杂度接近)


spfa+stack

#include <iostream>#include <cstdio>#include <cctype>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <sstream>#include <stack>using namespace std;#define MAX 30000+5#define MAXN 100000+5typedef long long LL;typedef unsigned long long ull;const double pi=3.141592653589793;const int INF=0x3f3f3f3f;const int INFF=1e9;const double inf=1e18;const double eps=1e-10;const int mod=1000000007;const int prime=999983;struct Edge{    int v,cost,next;}edge[150005];struct node{    int id,val;    bool operator<(const node &a)const{        return val>a.val;    }}x;int head[30005];int dis[30005];int vis[30005];int sstack[30005];int tot;inline int read_int(){    int ret=0;    char tmp;    while(!isdigit(tmp=getchar()));    do{        ret=(ret<<3)+(ret<<1)+tmp-'0';    }while(isdigit(tmp=getchar()));    return ret;}void add_edge(int a,int b,int c){    edge[tot].v=b;    edge[tot].cost=c;    edge[tot].next=head[a];    head[a]=tot++;}void spfa(int s){    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    int top=0;    sstack[top++]=s;    dis[s]=0;    vis[s]=1;    while(top!=0){        int q=sstack[--top];        vis[q]=0;        for(int i=head[q];i!=-1;i=edge[i].next){            int v=edge[i].v;            int cost=edge[i].cost;            if(dis[v]>dis[q]+cost){                dis[v]=dis[q]+cost;                if(!vis[v]){                    vis[v]=1;                    sstack[top++]=v;                }            }        }    }}int main(){    int n,m;    scanf("%d%d",&n,&m);    memset(head,-1,sizeof(head));    tot=0;    for(int i=0;i<m;i++){        int a=read_int();        int b=read_int();        int c=read_int();        add_edge(a,b,c);    }    spfa(1);    printf("%d\n",dis[n]);    return 0;}

dijkstra+heap

#include <iostream>#include <cstdio>#include <cctype>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <sstream>#include <stack>using namespace std;#define MAX 30000+5#define MAXN 100000+5typedef long long LL;typedef unsigned long long ull;const double pi=3.141592653589793;const int INF=0x3f3f3f3f;const int INFF=1e9;const double inf=1e18;const double eps=1e-10;const int mod=1000000007;const int prime=999983;struct Edge{    int v,cost,next;}edge[150005];struct node{    int id,val;    bool operator<(const node &a)const{        return val>a.val;    }}x;int head[30005];int dis[30005];int vis[30005];int tot;inline int read_int(){    int ret=0;    char tmp;    while(!isdigit(tmp=getchar()));    do{        ret=(ret<<3)+(ret<<1)+tmp-'0';    }while(isdigit(tmp=getchar()));    return ret;}void add_edge(int a,int b,int c){    edge[tot].v=b;    edge[tot].cost=c;    edge[tot].next=head[a];    head[a]=tot++;}void dijkstra(int s){    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    priority_queue<node> q;    x.id=s;    x.val=0;    dis[s]=0;    q.push(x);    while(!q.empty()){        x=q.top();        q.pop();        int num=x.id;        if(vis[num]) continue;        vis[num]=1;        for(int i=head[num];i!=-1;i=edge[i].next){            int vv=edge[i].v;            int cost=edge[i].cost;            if(!vis[vv]&&dis[vv]>dis[num]+cost){                dis[vv]=dis[num]+cost;                x.id=vv;                x.val=dis[vv];                q.push(x);            }        }    }}int main(){    int n,m;    scanf("%d%d",&n,&m);    memset(head,-1,sizeof(head));    tot=0;    for(int i=0;i<m;i++){        int a=read_int();        int b=read_int();        int c=read_int();        add_edge(a,b,c);    }    dijkstra(1);    printf("%d\n",dis[n]);    return 0;}

poj 1062

题意:一个比较明显的最短路,加上了等级。

题解:枚举最高等级,然后把等级不满足的点直接vis[x]=1记作已经访问过。

然后dijkstra即可

for(int i=mini;i<=maxn;i++){        memset(vis,0,sizeof(vis));        memset(dis,INF,sizeof(dis));        for(int j=1;j<=n;j++){            if(level[j]>i||i-level[j]>m) vis[j]=1;        }        dis[0]=0;        while(1){            int x=n+1;            for(int i=0;i<=n;i++){                if(!vis[i]&&dis[i]<dis[x]) x=i;            }            if(x==n+1) break;            vis[x]=1;            for(int i=0;i<=n;i++){                if(!vis[i]) dis[i]=min(dis[i],dis[x]+edge[x][i]);            }        }        ans=min(ans,dis[1]);    }    printf("%d\n",ans);


lightoj 1074

题意:很明显是最短路哇

题解:spfa判下负环即可。水水哒

/**********************************************************************************************************************************************************************************/

HDU 4370(转自kuangbin大神blog)(绝对好题***)

显然,题目给的是一个0/1规划模型。

解题的关键在于如何看出这个模型的本质。

3个条件明显在刻画未知数之间的关系,从图论的角度思考问题,容易得到下面3个结论:

1.X12+X13+...X1n=1 于是1号节点的出度为1

2..X1n+X2n+...Xn-1n=1 于是n号节点的入度为1

3.∑Xki =∑Xij 于是2~n-1号节点的入度必须等于出度

于是3个条件等价于一条从1号节点到n号节点的路径,故Xij=1表示需要经过边(i,j),代价为Cij。Xij=0表示不经过边(i,j)。注意到Cij非负且题目要求总代价最小,因此最优答案的路径一定可以对应一条简单路径。

最终,我们直接读入边权的邻接矩阵,跑一次1到n的最短路即可,记最短路为path。

以上情况设为A

非常非常非常非常非常非常非常非常抱歉,简单路径只是充分条件,但不必要。(对造成困扰的队伍深表歉意)

漏了如下的情况B:

从1出发,走一个环(至少经过1个点,即不能是自环),回到1;从n出发,走一个环(同理),回到n。

容易验证,这是符合题目条件的。且A || B为该题要求的充要条件。

由于边权非负,于是两个环对应着两个简单环。

本程序用SPFA来完成最短路。但是由于要计算从出发点出发的闭环的路径长度。所以要在普通SPFA的基础上做点变化。就是把dist[start]设为INF。同时一开始并不是让出发点入队,而是让出发点能够到达的点入队。

故最终答案为min(path,c1+c2)(用前向星建图比较好)

<span style="font-size:12px;">#include <iostream>#include <cstdio>#include <cctype>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <sstream>#include <stack>using namespace std;#define MAX 30000+5#define MAXN 100000+5typedef long long LL;typedef unsigned long long ull;const double pi=3.141592653589793;const int INF=0x3f3f3f3f;const int INFF=1e9;const double inf=1e18;const double eps=1e-10;const int mod=1000000007;const int prime=999983;inline int read_int(){    int ret=0;    char tmp;    while(!isdigit(tmp=getchar()));    do{        ret=(ret<<3)+(ret<<1)+tmp-'0';    }while(isdigit(tmp=getchar()));    return ret;}struct Edge{    int v,cost,next;}edge[100000];int head[305];int dis[305];int vis[305];int tot;void add_edge(int a,int b,int c){    edge[tot].v=b;    edge[tot].cost=c;    edge[tot].next=head[a];    head[a]=tot++;}void spfa(int s){    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    queue<int> q;    for(int i=head[s];i!=-1;i=edge[i].next){        int k=edge[i].v;        if(k!=s){            dis[k]=edge[i].cost;            vis[k]=1;            q.push(k);        }    }    while(!q.empty()){        int x=q.front();        q.pop();        vis[x]=0;        for(int i=head[x];i!=-1;i=edge[i].next){            int k=edge[i].v;            int cost=edge[i].cost;            if(dis[k]>dis[x]+cost){                dis[k]=dis[x]+cost;                if(!vis[k]){                    vis[k]=1;                    q.push(k);                }            }        }    }}int main(){    int n;    while(~scanf("%d",&n)){        memset(edge,INF,sizeof(edge));        memset(head,-1,sizeof(head));        tot=0;        for(int i=1;i<=n;i++){            for(int j=1;j<=n;j++){                int a;                scanf("%d",&a);                add_edge(i,j,a);            }        }        spfa(1);        int path=dis[n];        int c1=dis[1];        spfa(n);        int c2=dis[n];        printf("%d\n",min(path,c1+c2));    }    return 0;}

poj 3169

题意:当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些。FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食。奶牛排在队伍中的顺序和它们的编号是相同的。因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上。即使说,如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标。

一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数L。另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数D。给出ML条关于两头奶牛间有好感的描述,再给出MD条关于两头奶牛间存有反感的描述。(1<=ML,MD<=10000,1<=L,D<=1000000)

你的工作是:如果不存在满足要求的方案,输出-1;如果1号奶牛和N号

奶牛间的距离可以任意大,输出-2;否则,计算出在满足所有要求的情况下,1号奶牛和N号奶牛间可能的最大距离。


题解:这题给出了一些好感的关系,首先题目说每个牛站的位置是按照标号顺序的,所以3号的位置肯定大于等于1号。

所以一种情况就是AB最大相差C,就是B-A<=C,即为B<=A+C,这是A->B之间有一条权值C的有向边。

AB相差最小为C,就是B-A>=C,即为B>=A+C,化成A<=B-C,这是B->A之间有一条权值为-C的有向边

建图之后spfa跑一遍(因为有负权值),如果dis[n]==INF的时候就是1-n之间的没有最短路,可以任意距离,输出-2

有负环就是-1这个队伍不能排(我一开始-1 -2搞反了)

<span style="font-size:12px;">#include <iostream>#include <cstdio>#include <cctype>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <sstream>#include <stack>using namespace std;#define MAX 30000+5#define MAXN 100000+5typedef long long LL;typedef unsigned long long ull;const double pi=3.141592653589793;const int INF=0x3f3f3f3f;const int INFF=1e9;const double inf=1e18;const double eps=1e-10;const int mod=1000000007;const int prime=999983;inline int read_int(){    int ret=0;    char tmp;    while(!isdigit(tmp=getchar()));    do{        ret=(ret<<3)+(ret<<1)+tmp-'0';    }while(isdigit(tmp=getchar()));    return ret;}struct Edge{    int v,cost,next;}edge[20000];int head[1005];int dis[1005];int vis[1005];int xcount[1005];int tot;int flag;void add_edge(int a,int b,int c){    edge[tot].v=b;    edge[tot].cost=c;    edge[tot].next=head[a];    head[a]=tot++;}void spfa(int s,int n){    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    memset(xcount,0,sizeof(xcount));    queue<int> q;    dis[s]=0;    vis[s]=1;    xcount[s]++;    q.push(s);    while(!q.empty()){        int x=q.front();        q.pop();        vis[x]=0;        for(int i=head[x];i!=-1;i=edge[i].next){            int k=edge[i].v;            int cost=edge[i].cost;            //printf("%d %d %d \n",x,k,cost);            if(dis[k]>dis[x]+cost){                dis[k]=dis[x]+cost;                if(!vis[k]){                    vis[k]=1;                    xcount[k]++;                    q.push(k);                    if(xcount[k]>n){                        flag=1;                        return ;                    }                }            }        }    }}int main(){    int n,l,d;    scanf("%d%d%d",&n,&l,&d);    tot=0;    memset(head,-1,sizeof(head));    for(int i=0;i<l;i++){        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        add_edge(a,b,c);    }    for(int i=0;i<d;i++){        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        add_edge(b,a,-c);    }    flag=0;    spfa(1,n);    if(flag) printf("-1\n");    else if(dis[n]==INF) printf("-2\n");    else printf("%d\n",dis[n]);    return 0;}</span>


hdu 4725

题意:给你n个点,每个点属于某个层,点之间有m条无向边,相邻的层之间还能互相走,花费是c

题解:首先看百度上说要拆点,后来学长没用拆点就过去了。

记录每个层有哪些点,然后用dijkstra+heap的时候,点的结构体中要加个判断is_node,如果是点,他就可以走向他所连的边,还有他的上一层或者下一层,都进队。

如果是层,那么可以把这层上的所有点(未访问过并且dis被更新过的)放进队列中,即可。(前向星建图head没有初始化又看了好久,还得多练,这题也是虚掉了不敢做,so weak)

#include <iostream>#include <cstdio>#include <cctype>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <sstream>#include <stack>using namespace std;#define MAX 30000+5#define MAXN 100000+5typedef long long LL;typedef unsigned long long ull;const double pi=3.141592653589793;const int INF=0x3f3f3f3f;const int INFF=1e9;const double inf=1e18;const double eps=1e-10;const int mod=1000000007;const int prime=999983;inline int read_int(){    int ret=0;    char tmp;    while(!isdigit(tmp=getchar()));    do{        ret=(ret<<3)+(ret<<1)+tmp-'0';    }while(isdigit(tmp=getchar()));    return ret;}struct Node{    int v,val;    bool is_node;    bool operator < (const Node &a)const{        return val > a.val;    }};struct Edge{    int v,cost,next;}edge[2*MAXN];int n,m,c;vector<int> v[MAXN];int lay[MAXN];int head[MAXN];int dis[MAXN];int vis[MAXN];int vis_l[MAXN];int tot;int max_l,min_l;void add_edge(int a,int b,int c){    edge[tot]=(Edge){b,c,head[a]};    head[a]=tot++;}void dijkstra(int s){    memset(vis,0,sizeof(vis));    memset(vis_l,0,sizeof(vis_l));    memset(dis,INF,sizeof(dis));    priority_queue<Node> q;    q.push((Node){s,0,1});    dis[s]=0;    while(!q.empty()){        Node now=q.top();        q.pop();        int num=now.v;        if(now.is_node){            if(vis[num]) continue;            vis[num]=1;            for(int i=head[num];i!=-1;i=edge[i].next){                int k=edge[i].v;                int cost=edge[i].cost;                if(!vis[k]&&dis[k]>dis[num]+cost){                    dis[k]=dis[num]+cost;                    q.push((Node){k,dis[k],1});                }            }            if(lay[num]>min_l){                q.push((Node){lay[num]-1,dis[num]+c,0});            }            if(lay[num]<max_l){                q.push((Node){lay[num]+1,dis[num]+c,0});            }        }        else{            if(vis_l[num]) continue;            vis_l[num]=1;            for(int i=0;i<v[num].size();i++){                int k=v[num][i];                if(!vis[k]&&dis[k]>now.val){                    dis[k]=now.val;                    q.push((Node){k,dis[k],1});                }            }        }    }}int main(){    int T;    scanf("%d",&T);    for(int t=1;t<=T;t++){        scanf("%d%d%d",&n,&m,&c);        tot=0;        max_l=0;        min_l=INF;        memset(head,-1,sizeof(head));        for(int i=1;i<=n;i++) v[i].clear();        for(int i=1;i<=n;i++){            scanf("%d",&lay[i]);            v[lay[i]].push_back(i);            max_l=max(max_l,lay[i]);            min_l=min(min_l,lay[i]);        }        for(int i=0;i<m;i++){            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            add_edge(a,b,c);            add_edge(b,a,c);        }        dijkstra(1);        printf("Case #%d: ",t);        if(dis[n]==INF) printf("-1\n");        else printf("%d\n",dis[n]);    }    return 0;}

还有个神马最短路+最大流还不会,改天做完了再发



0 0
原创粉丝点击