zoukankan      html  css  js  c++  java
  • 选拔赛-最短路

    还是太菜了吧,,这都不会

    裸的最短路??

    -_-||

    第一种方法:

    每个点有记录两个状态,红灯和绿灯分开记

    抄的牛的代码,spfa。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 const int maxn=10010;
     7 const int maxe=20010;
     8 const int inf=0x3f3f3f3f;
     9 
    10 int n,m,ss,ee;
    11 int t;
    12 
    13 int dis[maxn][2];  //双状态
    14 int inq[maxn][2];
    15 
    16 struct edge
    17 {
    18     int v,nex;
    19     int a,b;
    20 }e[maxe*2];
    21 
    22 int head[maxn];
    23 int cnt;
    24 void add(int u,int v,int a,int b)
    25 {
    26     e[cnt].v=v;
    27     e[cnt].a=a;
    28     e[cnt].b=b;
    29     e[cnt].nex=head[u];
    30     head[u]=cnt++;
    31 }
    32 
    33 void spfa()
    34 {
    35     queue<int>q;
    36     q.push(ss);
    37     q.push(0);
    38     dis[ss][0]=0;
    39     while(!q.empty())
    40     {
    41         int u=q.front();
    42         q.pop();
    43         int mask=q.front();
    44         q.pop();
    45         inq[u][mask]=0;
    46         for(int i=head[u];i!=-1;i=e[i].nex)
    47         {
    48             int v=e[i].v;
    49             int a=e[i].a;
    50             int b=e[i].b;
    51             int cc=mask?b:a;
    52             int mask2=(cc&1)^mask;   // 位运算很巧妙!!
    53             if(dis[v][mask2]>dis[u][mask]+cc)
    54             {
    55                 dis[v][mask2]=dis[u][mask]+cc;
    56                 if(!inq[v][mask2])
    57                 {
    58                     inq[v][mask2]=1;
    59                     q.push(v);
    60                     q.push(mask2);
    61                 }
    62             }
    63         }
    64     }
    65 }
    66 
    67 int main()
    68 {
    69     int T;
    70     int u,v,a,b;
    71     scanf("%d",&T);
    72     while(T--)
    73     {
    74         scanf("%d%d%d%d",&n,&m,&ss,&ee);
    75         for(int i=0;i<=n;i++) head[i]=-1;
    76         cnt=0;
    77         memset(inq,0,sizeof(inq));
    78         memset(dis,0x3f3f3f,sizeof dis);
    79         for(int i=0;i<m;i++)
    80         {
    81             scanf("%d%d%d%d",&u,&v,&a,&b);
    82             add(u,v,a,b);
    83             add(v,u,a,b);
    84         }
    85         spfa();
    86         int ans=min(dis[ee][0],dis[ee][1]);
    87         if(ans==inf) puts("-1");
    88         else printf("%d
    ",ans);
    89     }
    90 }

    第二种方法:

    拆点。。

    对每个点 x拆成两个点 2x,2x+1  分别表示绿灯状态和红灯状态。
    对于绿灯奇数时间的路线 a,b 连接  2a2b+1 和 2b2a+1,其他路线类似。
    最后跑一遍标准的 SPFA 即可

    今天好累,不想打了,先直接贴上吧。。

     1 #include<bits/stdc++.h>
     2 #define IN(x) (x<<1)
     3 #define OUT(x) (x<<1|1)
     4 using namespace std;
     5 
     6 const int maxn=10000*2+10;
     7 const int INF=~0U>>2;
     8 
     9 struct edge{int from,to,dis;};
    10 
    11 struct SPFA{
    12     int n;
    13     vector<int>G[maxn];
    14     vector<edge>E;
    15     int d[maxn];
    16     bool vis[maxn];
    17     
    18     void init(int n){
    19         this->n=n;
    20         for(int i=0;i<=n;i++)G[i].clear();
    21         E.clear();
    22     }
    23 
    24     void addedge(int from,int to,int dis){
    25         E.push_back((edge){from,to,dis});
    26         G[from].push_back(E.size()-1);
    27     }
    28 
    29     void exec(int S){
    30         for(int i=0;i<=n;i++)d[i]=INF,vis[i]=0;
    31         d[S]=0,vis[S]=1;
    32         queue<int>Q;
    33         Q.push(S);
    34         while(!Q.empty()){
    35             int x=Q.front();
    36             Q.pop();vis[x]=0;
    37             for(int i:G[x]){
    38                 edge &e=E[i];
    39                 if(d[e.to]>d[e.from]+e.dis){
    40                     d[e.to]=d[e.from]+e.dis;
    41                     if(!vis[e.to]){
    42                         vis[e.to]=1;
    43                         Q.push(e.to);
    44                     }
    45                 }
    46             }
    47         }
    48     }
    49 
    50     int value(int x){return d[x];}
    51 }app;
    52 
    53 
    54 
    55 int main(){
    56     int T;
    57     scanf("%d",&T);
    58     while(T--){
    59         int n,m,s,t;
    60         scanf("%d%d%d%d",&n,&m,&s,&t);
    61         s--,t--;
    62         app.init(n*2);
    63         for(int i=1;i<=m;i++){
    64             int a,b,c,d;
    65             scanf("%d%d%d%d",&a,&b,&c,&d);
    66             a--,b--;
    67             app.addedge(IN(a),IN(b)^(c&1),c);
    68             app.addedge(IN(b),IN(a)^(c&1),c);
    69             app.addedge(OUT(a),OUT(b)^(d&1),d);
    70             app.addedge(OUT(b),OUT(a)^(d&1),d);
    71         }    
    72         app.exec(IN(s));
    73         printf("%d
    ",min(app.value(IN(t)),app.value(OUT(t))));
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    【算法学习笔记】27.动态规划 解题报告 SJTU OJ 1254 传手绢
    【算法学习笔记】26.扫描维护法 解题报告 SJTU OJ 1133 数星星
    【算法学习笔记】25.贪心法 均分纸牌问题的分析
    【算法学习笔记】24.记忆化搜索 解题报告 SJTU OJ 1002 二哥种花生
    【算法学习笔记】23.动态规划 解题报告 SJTU OJ 1280 整装待发
    【算法学习笔记】22.算法设计初步 二分查找 上下界判断
    【算法学习笔记】21.算法设计初步 求第k个数 划分法 快排法
    【算法学习笔记】20.算法设计初步 归并排序 求逆序数
    【算法学习笔记】19.算法设计初步 最大子列和问题的几种方法
    【算法学习笔记】18.暴力求解法06 隐式图搜索2 八数码问题 未启发
  • 原文地址:https://www.cnblogs.com/yijiull/p/6711314.html
Copyright © 2011-2022 走看看