• 最短路拓展


     1 #include<cstdio> 
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=1e6+10;
     8 const int inf=1e9;
     9 struct node{
    10     int v;
    11     int c;
    12     node(int _v=0,int _c=0):v(_v),c(_c) {}
    13     bool operator < (const node &r)const{
    14     return c>r.c;
    15     }
    16 };
    17 struct Edge{
    18     int v,cost;
    19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
    20 };
    21 vector<Edge>E[maxn];
    22 bool vis[maxn];
    23 int dist[maxn];
    24 int n,s;
    25 
    26 void addedge(int u,int v,int w)
    27 {
    28     E[u].push_back(Edge(v,w));
    29 }
    30 
    31 void dij()
    32 {
    33     memset(vis,false,sizeof(vis));
    34     for ( int i=1;i<=n;i++ ) dist[i]=inf;
    35     priority_queue<node>que;
    36     while ( !que.empty() ) que.pop();
    37     dist[s]=0;
    38     que.push(node(s,0));
    39     node tmp;
    40     while ( !que.empty() )
    41     {
    42         tmp=que.top();
    43         que.pop();
    44         int u=tmp.v;
    45         if ( vis[u] ) continue;
    46         vis[u]=true;
    47         for ( int i=0;i<E[u].size();i++ )
    48         {
    49             int v=E[u][i].v;
    50             int cost=E[u][i].cost;
    51             if ( !vis[v] && dist[v]>dist[u]+cost )
    52             {
    53                 dist[v]=dist[u]+cost;
    54                 que.push(node(v,dist[v]));
    55             }
    56         }
    57     }
    58 }
    Dijkstra算法模板
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=1010;
     8 const int inf=1e9;
     9 struct Edge{
    10     int v;
    11     int cost;
    12     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
    13 }; 
    14 vector<Edge>E[maxn];
    15 bool vis[maxn];
    16 int cnt[maxn];
    17 int dist[maxn];
    18 int s,n;
    19 
    20 void addedge(int u,int v,int w)
    21 {
    22     E[u].push_back(Edge(v,w));
    23 }
    24 
    25 bool spfa()
    26 {
    27     memset(vis,false,sizeof(vis));
    28     for ( int i=1;i<=n;i++ ) dist[i]=inf;
    29     vis[s]=true;
    30     dist[s]=0;
    31     queue<int>que;
    32     while ( !que.empty() ) que.pop();
    33     que.push(s);
    34     memset(cnt,0,sizeof(cnt));
    35     cnt[s]=1;
    36     while ( !que.empty() )
    37     {
    38         int u=que.front();
    39         que.pop();
    40         vis[u]=false;
    41         for ( int i=0;i<E[u].size();i++ )
    42         {
    43             int v=E[u][i].v;
    44             int cost=E[u][i].cost;
    45             if ( dist[v]>dist[u]+cost )
    46             {
    47                 dist[v]=dist[u]+cost;
    48                 if ( !vis[v] )
    49                 {
    50                     vis[v]=true;
    51                     que.push(v);
    52                     if ( ++cnt[v]>n ) return false;    
    53                 }    
    54             }
    55         }
    56     }
    57     return true;
    58 }
    Spfa模板

    1.(UVA247)https://vjudge.net/problem/UVA-247

    题意:给定n个人和m组关系(x,y表示x打电话给y,单向),找出所有的环,分别输出每个环内的元素

    分析:当vis[x][y]=vis[y][x]=true表示这两个点处于一个环内,利用floyd传递闭包,最后注意输出格式

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<map>
     5 #include<string>
     6 #include<iostream>
     7 #include<vector>
     8 using namespace std;
     9 const int maxn=30;
    10 map<string,int>mp;
    11 map<int,string>mp_;
    12 bool vis[maxn][maxn];
    13 int belong[maxn];
    14 vector<int>G[maxn];
    15 
    16 int main()
    17 {
    18     int n,m,cnt,num,id1,id2,h=0;
    19     string s1,s2;
    20     while ( scanf("%d%d",&n,&m)!=EOF && (n+m) )
    21     {
    22         mp.clear();
    23         mp_.clear();
    24         memset(vis,false,sizeof(vis));
    25         memset(belong,0,sizeof(belong));
    26         for ( int i=1;i<=n;i++ ) 
    27         {
    28             vis[i][i]=true;
    29             G[i].clear();
    30         }
    31         cnt=0;
    32         for ( int i=1;i<=m;i++ )
    33         {
    34             cin>>s1>>s2;
    35             if ( mp.find(s1)==mp.end() ) mp[s1]=++cnt,mp_[cnt]=s1;
    36             id1=mp[s1];
    37             if ( mp.find(s2)==mp.end() ) mp[s2]=++cnt,mp_[cnt]=s2;
    38             id2=mp[s2];
    39             vis[id1][id2]=true;
    40         }
    41         for ( int k=1;k<=n;k++ )
    42         {
    43             for ( int i=1;i<=n;i++ )
    44             {
    45                 for ( int j=1;j<=n;j++ )
    46                 {
    47                     if ( vis[i][k] && vis[k][j] ) vis[i][j]=true;    
    48                 }    
    49             } 
    50         }
    51         num=0;
    52         for ( int i=1;i<=n;i++ )
    53         {
    54             if ( belong[i] ) continue;
    55             belong[i]=++num;
    56             G[num].push_back(i);
    57             for ( int j=i+1;j<=n;j++ )
    58             {
    59                 if ( belong[j] ) continue;
    60                 if ( vis[i][j] && vis[j][i] ) 
    61                 {
    62                     belong[j]=belong[i];
    63                     G[num].push_back(j);
    64                 }
    65             }
    66         }
    67         if ( h ) printf("
    ");
    68         printf("Calling circles for data set %d:
    ",++h);
    69         for ( int i=1;i<=num;i++ )
    70         {
    71             for ( int j=0;j<G[i].size();j++ )
    72             {
    73                 cout<<mp_[G[i][j]];
    74                 if ( j<G[i].size()-1 ) printf(", ");
    75                 else printf("
    ");
    76             }
    77         }
    78     }
    79     return 0;
    80 }
    UVA247

    2.(UVA10048)https://vjudge.net/problem/UVA-10048

    题意:给定c个点和s条边的有向图,边权代表该路径上的噪音值。每次询问输入两个点,求这两个点间最大噪音值最小的值

     分析:Dijkstra算法中每次松弛将本来的dist[v]=dist[u]+cost变成dist[v]=max(dist[u],cost) (在满足条件的前提下)

    floyd算法松弛过程同Dijkastra

     1 #include<cstdio> 
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=110;
     8 const int inf=1e9;
     9 struct node{
    10     int v;
    11     int c;
    12     node(int _v=0,int _c=0):v(_v),c(_c) {}
    13     bool operator < (const node &r)const{
    14     return c>r.c;
    15     }
    16 };
    17 struct Edge{
    18     int v,cost;
    19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
    20 };
    21 vector<Edge>E[maxn];
    22 bool vis[maxn];
    23 int dist[maxn][maxn];
    24 int n;
    25 
    26 void addedge(int u,int v,int w)
    27 {
    28     E[u].push_back(Edge(v,w));
    29 }
    30 
    31 void dij(int s)
    32 {
    33     memset(vis,false,sizeof(vis));
    34     for ( int i=1;i<=n;i++ ) dist[s][i]=inf;
    35     priority_queue<node>que;
    36     while ( !que.empty() ) que.pop();
    37     dist[s][s]=0;
    38     que.push(node(s,0));
    39     node tmp;
    40     while ( !que.empty() )
    41     {
    42         tmp=que.top();
    43         que.pop();
    44         int u=tmp.v;
    45         if ( vis[u] ) continue;
    46         vis[u]=true;
    47         for ( int i=0;i<E[u].size();i++ )
    48         {
    49             int v=E[u][i].v;
    50             int cost=E[u][i].cost;
    51             int x=max(cost,dist[s][u]);
    52             if ( !vis[v] && dist[s][v]>x )
    53             {
    54                 dist[s][v]=x;
    55                 que.push(node(v,dist[s][v]));
    56             }
    57         }
    58     }
    59 }
    60 
    61 int main()
    62 {
    63     int m,q,h=0;
    64     while ( scanf("%d%d%d",&n,&m,&q)!=EOF && (n+m+q) )
    65     {
    66         for ( int i=1;i<=n;i++ )
    67         {
    68             for ( int j=1;j<=n;j++ ) dist[i][j]=inf;
    69             dist[i][i]=0;
    70             E[i].clear();
    71         }
    72         for ( int i=1;i<=m;i++ )
    73         {
    74             int u,v,w;
    75             scanf("%d%d%d",&u,&v,&w);
    76             addedge(u,v,w);
    77             addedge(v,u,w);
    78         }
    79         for ( int i=1;i<=n;i++ )
    80         {
    81             dij(i);
    82         }
    83         if ( h ) printf("
    ");
    84         printf("Case #%d
    ",++h);
    85         while ( q-- )
    86         {
    87             int u,v;
    88             scanf("%d%d",&u,&v);
    89             if ( dist[u][v]==inf ) printf("no path
    ");
    90             else printf("%d
    ",dist[u][v]);
    91         }
    92     }
    93     return 0;
    94 }
    UVA10048(Dijkstra)
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=110;
     6 const int inf=1e9;
     7 int dist[maxn][maxn];
     8 
     9 void floyd(int n)
    10 {
    11     for ( int k=1;k<=n;k++ )
    12     {
    13         for ( int i=1;i<=n;i++ )
    14         {
    15             for ( int j=1;j<=n;j++ )
    16             {
    17                 if ( dist[i][k]==inf || dist[k][j]==inf ) continue;
    18                 if ( dist[i][j]==inf ) dist[i][j]=max(dist[i][k],dist[k][j]);
    19                 else dist[i][j]=min(dist[i][j],max(dist[i][k],dist[k][j]));
    20             }
    21         }
    22     }
    23 }
    24 
    25 int main()
    26 {
    27     int n,m,q,h=0;
    28     while ( scanf("%d%d%d",&n,&m,&q)!=EOF && (n+m+q) )
    29     {
    30         for ( int i=1;i<=n;i++ )
    31         {
    32             for ( int j=1;j<=n;j++ ) dist[i][j]=inf;
    33             dist[i][i]=0;
    34         }
    35         for ( int i=1;i<=m;i++ )
    36         {
    37             int u,v,w;
    38             scanf("%d%d%d",&u,&v,&w);
    39             dist[u][v]=min(dist[u][v],w);
    40             dist[v][u]=min(dist[v][u],w);
    41         }
    42         floyd(n);
    43         if ( h ) printf("
    ");
    44         printf("Case #%d
    ",++h);
    45         while ( q-- )
    46         {
    47             int u,v;
    48             scanf("%d%d",&u,&v);
    49             if ( dist[u][v]==inf ) printf("no path
    ");
    50             else printf("%d
    ",dist[u][v]);
    51         }
    52     }
    53     return 0;
    54 }
    UVA10048(floyd)

    3.(UVA658)https://vjudge.net/problem/UVA-658

    题意:有一个长度为n的bug,有m个补丁,每个补丁有3个值,分别代表花费的时间,bug在补丁前的状态(“0”代表无所谓,“-”代表bug不存在,“+”代表bug存在),bug在补丁后的状态(“0”代表不变,“+”代表该位置出现bug,“-”代表该位置没有bug),一个补丁可以打多次,求最小的花费时间

    分析:将bug转化为二进制形式,0表示该位置有bug,1表示该位置没有bug。所以总共有(1<<n)-1种状态。每次更新时访问所有的补丁(可以等效成“边”) ,若满足条件则转移状态,最后判断(1<<n)-1这个状态

      1 #include<cstdio> 
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<queue>
      6 using namespace std;
      7 const int maxn=2e6+10;
      8 const int N=22;
      9 const int maxm=110;
     10 const int inf=1e9;
     11 struct node{
     12     int v;
     13     int c;
     14     node(int _v=0,int _c=0):v(_v),c(_c) {}
     15     bool operator < (const node &r)const{
     16     return c>r.c;
     17     }
     18 };
     19 bool vis[maxn];
     20 int dist[maxn];
     21 int s;
     22 char s1[maxm][N],s2[maxm][N];
     23 int w[maxm],m;
     24 
     25 void dij(int n)
     26 {
     27     memset(vis,false,sizeof(vis));
     28     for ( int i=0;i<=n;i++ ) dist[i]=inf;
     29     priority_queue<node>que;
     30     while ( !que.empty() ) que.pop();
     31     dist[s]=0;
     32     que.push(node(s,0));
     33     node tmp;
     34     while ( !que.empty() )
     35     {
     36         tmp=que.top();
     37         que.pop();
     38         int u=tmp.v;
     39         if ( vis[u] ) continue;
     40         vis[u]=true;
     41         for ( int i=1;i<=m;i++ )
     42         {
     43             bool flag=true;
     44             int len=strlen(s1[i]);
     45             for ( int j=0;j<len;j++ )
     46             {
     47                 if ( s1[i][j]=='0' ) continue;
     48                 else if ( s1[i][j]=='+' )
     49                 {
     50                     if ( ((1<<j)&u) )
     51                     {
     52                         flag=false;
     53                         break;
     54                     }
     55                 }
     56                 else if ( s1[i][j]=='-' ) 
     57                 {
     58                     if ( !((1<<j)&u) )
     59                     {
     60                         flag=false;
     61                         break;
     62                     }    
     63                 } 
     64             }
     65             if ( !flag ) continue;
     66             int v=u;
     67             for ( int j=0;j<len;j++ )
     68             {
     69                 if ( s2[i][j]=='0' ) continue;
     70                 else if ( s2[i][j]=='+' )
     71                 {
     72                     if ( ((1<<j)&v) ) v^=(1<<j);
     73                 }
     74                 else if ( s2[i][j]=='-' ) 
     75                 {
     76                     if ( !((1<<j)&v) ) v|=(1<<j);
     77                 } 
     78             }
     79             int cost=w[i];
     80             if ( !vis[v] && dist[v]>dist[u]+cost )
     81             {
     82                 dist[v]=dist[u]+cost;
     83                 que.push(node(v,dist[v]));
     84             }
     85         }
     86     }
     87 }
     88 
     89 int main()
     90 {
     91     int n,h=0,p;
     92     while ( scanf("%d%d",&n,&m)!=EOF && (n+m) ) 
     93     {
     94         p=(1<<n)-1;
     95         for ( int i=1;i<=m;i++ )
     96         {
     97             scanf("%d%s%s",&w[i],s1[i],s2[i]);
     98         }
     99         s=0;
    100         dij(p);
    101         printf("Product %d
    ",++h);
    102         if ( dist[p]!=inf ) printf("Fastest sequence takes %d seconds.
    
    ",dist[p]);
    103         else printf("Bugs cannot be fixed.
    
    ");
    104     }
    105     return 0;
    106 }
    UVA658

    4.(UVA11374)https://vjudge.net/problem/UVA-11374

    题意:机场快线分为经济线和商业线,你有一张商业线的车票,可以坐一站商业线,其他时候都只能做经济线,不考虑换乘时间,求一条最快去机场的线路。输入第一行为n,s,e,分别表示点数,起点和终点。下一行一个m表示经济线的线路数,接下来m行有x,y,z表示x-y(双向)花费z分钟。接下来一行一个k表示商业线的线路数,接下来k行x,y,z表示x-y(双向)花费z。输出三行,第一行表示线路,第二行表示换乘商业线的编号,第三行表示时间

    分析:首先需要分别以s和e为起点进行两次最短路算法。剩下的只要枚举坐的是哪趟商业线即可,对于任意一条含商业线的路线所花费的时间为d(s,x)+z+d(y,e)与d(s,e)进行比较即可。注意如何打印路径。

      1 #include<cstdio> 
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<queue>
      6 using namespace std;
      7 const int maxn=5010;
      8 const int maxm=5010;
      9 const int inf=1e9;
     10 struct node{
     11     int v;
     12     int c;
     13     node(int _v=0,int _c=0):v(_v),c(_c) {}
     14     bool operator < (const node &r)const{
     15     return c>r.c;
     16     }
     17 };
     18 struct Edge{
     19     int v,cost;
     20     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
     21 };
     22 vector<Edge>E[maxn];
     23 bool vis[maxn];
     24 int dist[2][maxn];
     25 int pre[2][maxn];
     26 int n;
     27 int a[maxm],b[maxm],c[maxm];
     28 
     29 void addedge(int u,int v,int w)
     30 {
     31     E[u].push_back(Edge(v,w));
     32 }
     33 
     34 void dij(int s)
     35 {
     36     memset(vis,false,sizeof(vis));
     37     for ( int i=1;i<=n;i++ ) dist[0][i]=inf;
     38     memset(pre[0],-1,sizeof(pre[0]));
     39     priority_queue<node>que;
     40     while ( !que.empty() ) que.pop();
     41     dist[0][s]=0;
     42     que.push(node(s,0));
     43     node tmp;
     44     while ( !que.empty() )
     45     {
     46         tmp=que.top();
     47         que.pop();
     48         int u=tmp.v;
     49         if ( vis[u] ) continue;
     50         vis[u]=true;
     51         for ( int i=0;i<E[u].size();i++ )
     52         {
     53             int v=E[u][i].v;
     54             int cost=E[u][i].cost;
     55             if ( !vis[v] && dist[0][v]>dist[0][u]+cost )
     56             {
     57                 dist[0][v]=dist[0][u]+cost;
     58                 pre[0][v]=u;
     59                 que.push(node(v,dist[0][v]));
     60             }
     61         }
     62     }
     63 }
     64 
     65 void display(int u)
     66 {
     67     if ( pre[0][u]==-1 )
     68     {
     69         printf("%d",u);
     70         return;
     71     }
     72     display(pre[0][u]);
     73     printf(" %d",u);
     74 }
     75 
     76 int main()
     77 {
     78     int s,e,k,ans,cnt,m,h=0;
     79     while ( scanf("%d%d%d",&n,&s,&e)!=EOF )
     80     {
     81         for ( int i=1;i<=n;i++ ) E[i].clear();
     82         scanf("%d",&m);
     83         for ( int i=1;i<=m;i++ )
     84         {
     85             int u,v,w;
     86             scanf("%d%d%d",&u,&v,&w);
     87             addedge(u,v,w);
     88             addedge(v,u,w);
     89         }
     90         dij(e);
     91         for ( int i=1;i<=n;i++ )
     92         {
     93             dist[1][i]=dist[0][i];
     94             pre[1][i]=pre[0][i];
     95         }
     96         dij(s);
     97         scanf("%d",&k);
     98         for ( int i=1;i<=k*2;i+=2 )
     99         {
    100             scanf("%d%d%d",&a[i],&b[i],&c[i]);
    101             b[i+1]=a[i];
    102             a[i+1]=b[i];
    103             c[i+1]=c[i];
    104         }
    105         ans=dist[0][e];
    106         cnt=-1;
    107         for ( int i=1;i<=2*k;i++ )
    108         {
    109             int num=dist[0][a[i]]+c[i]+dist[1][b[i]];
    110             if ( num<ans )
    111             {
    112                 ans=num;
    113                 cnt=i;
    114             }
    115         }
    116         if ( h++>0 ) printf("
    ");
    117         if ( cnt==-1 ) 
    118         {
    119             display(e);
    120             printf("
    ");
    121             printf("Ticket Not Used
    ");
    122         }
    123         else 
    124         {
    125             display(a[cnt]);
    126             for ( int i=b[cnt];i!=e;i=pre[1][i] ) printf(" %d",i);
    127             printf(" %d
    ",e);
    128             printf("%d
    ",a[cnt]);
    129         }
    130         printf("%d
    ",ans);
    131     }
    132     return 0;
    133 }
    UVA11374

    5.(UVA10917)https://vjudge.net/problem/UVA-10917

    题意:有n个点和m条双向边,从起点1出发,去往终点2.每次只沿着满足如下条件道路的(A,B)走,存在一条从B出发的路,比所有从A出发回家的路都短。计算一共有多少条路

     分析:最短路+dfs,首先用最短路求出所有点到终点2的距离(用来判断某条边是否可走),设dp[i]为从i出发有多少条路可以到达终点,初始化dp[1]=1,其余均为0.然后通过dfs,从1出发。对于点u来说,当边(u,v)满足条件,则dp[u]+=dp[v]

     1 #include<cstdio> 
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=1e3+10;
     8 const int inf=1e9;
     9 struct node{
    10     int v;
    11     int c;
    12     node(int _v=0,int _c=0):v(_v),c(_c) {}
    13     bool operator < (const node &r)const{
    14     return c>r.c;
    15     }
    16 };
    17 struct Edge{
    18     int v,cost;
    19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
    20 };
    21 vector<Edge>E[maxn];
    22 bool vis[maxn];
    23 int dist[maxn],dp[maxn];
    24 int n,s,e;
    25 
    26 void addedge(int u,int v,int w)
    27 {
    28     E[u].push_back(Edge(v,w));
    29 }
    30 
    31 void dij()
    32 {
    33     memset(vis,false,sizeof(vis));
    34     for ( int i=1;i<=n;i++ ) dist[i]=inf;
    35     priority_queue<node>que;
    36     while ( !que.empty() ) que.pop();
    37     dist[s]=0;
    38     que.push(node(s,0));
    39     node tmp;
    40     while ( !que.empty() )
    41     {
    42         tmp=que.top();
    43         que.pop();
    44         int u=tmp.v;
    45         if ( vis[u] ) continue;
    46         vis[u]=true;
    47         for ( int i=0;i<E[u].size();i++ )
    48         {
    49             int v=E[u][i].v;
    50             int cost=E[u][i].cost;
    51             if ( !vis[v] && dist[v]>dist[u]+cost )
    52             {
    53                 dist[v]=dist[u]+cost;
    54                 que.push(node(v,dist[v]));
    55             }
    56         }
    57     }
    58 }
    59 
    60 int dfs(int u)
    61 {
    62     vis[u]=true;
    63     for ( int i=0;i<E[u].size();i++ )
    64     {
    65         int v=E[u][i].v;
    66         if ( dist[v]>=dist[u] ) continue;
    67         if ( vis[v] ) dp[u]+=dp[v];
    68         else dp[u]+=dfs(v);
    69     }
    70     return dp[u];
    71 }
    72 
    73 int main()
    74 {
    75     int m;
    76     while ( scanf("%d",&n)!=EOF && n )
    77     {
    78         scanf("%d",&m);
    79         for ( int i=1;i<=n;i++ ) E[i].clear();
    80         s=2;
    81         e=1;
    82         for ( int i=1;i<=m;i++ )
    83         {
    84             int u,v,w;
    85             scanf("%d%d%d",&u,&v,&w);
    86             addedge(u,v,w);
    87             addedge(v,u,w);
    88         }
    89         dij();
    90         memset(dp,0,sizeof(dp));
    91         memset(vis,false,sizeof(vis));    
    92         dp[s]=1;
    93         //vis[e]=true;
    94         dfs(e);
    95         printf("%d
    ",dp[1]);
    96     }
    97     return 0;
    98 }
    UVA10917

    6.(UVA10537)https://vjudge.net/problem/UVA-10537

    题意:运送货物需要缴纳路费,路过一个村庄需要缴纳一个单位的货物,路过城镇每20个货物需要缴纳1个单位的货物(70个需要缴纳4个)。输入时给定一个n表示道路的条数,接下来n行,每行两个字母(大写为城镇,小写为村庄),道路均为双向路。接下来一行包括一个p和两个字母,表示运送的货物数量、起点和终点。输出包括运送货物的最小值和对应线路(若有多条线路,输出字典序最小的)

    分析:用最短算法的逆推,设dist[i] 表示进入节点后至少有dist[i]单位的货物才能使达到目的地的货物数量足够,每次选择一个dist[i]最小的未标号结点,更新它所有的前驱,算出所有的dist。假设经过某个城镇后的数量为x,若x%19==0,则y=x/19。若x%19!=0,则y=x/19+1。则y为在该城镇所缴纳的货物

    注意:dist数组开longlong,图为无向图,可以直接用字符的阿斯克码当作结点的编号,注意打印路径的写法

     1 #include<cstdio> 
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 typedef long long ll; 
     8 const int maxn=155;
     9 const int n=150;
    10 const ll inf=1e18;
    11 struct node{
    12     int v;
    13     ll c;
    14     node(int _v=0,ll _c=0):v(_v),c(_c) {}
    15     bool operator < (const node &r)const{
    16         return c>r.c;
    17     }
    18 };
    19 vector<int>E[maxn];
    20 bool vis[maxn];
    21 ll dist[maxn],num;
    22 int s,e,pre[maxn];
    23 
    24 void addedge(int u,int v)
    25 {
    26     E[u].push_back(v);
    27 }
    28 
    29 void dij()
    30 {
    31     memset(vis,false,sizeof(vis));
    32     memset(pre,-1,sizeof(pre));
    33     for ( int i=0;i<=n;i++ ) dist[i]=inf;
    34     priority_queue<node>que;
    35     while ( !que.empty() ) que.pop();
    36     dist[s]=num;
    37     que.push(node(s,dist[s]));
    38     node tmp;
    39     while ( !que.empty() )
    40     {
    41         tmp=que.top();
    42         que.pop();
    43         int u=tmp.v;
    44         if ( vis[u] ) continue;
    45         vis[u]=true;
    46         for ( int i=0;i<E[u].size();i++ )
    47         {
    48             int v=E[u][i];
    49             if ( vis[v] ) continue;
    50             ll cost;
    51             if ( u>='a' ) cost=1;
    52             else 
    53             {
    54                 if ( tmp.c%19==0 ) cost=tmp.c/19;
    55                 else cost=tmp.c/19+1;    
    56             }
    57             if (dist[v]>dist[u]+cost || (dist[v]==dist[u]+cost&&pre[v]>u) )
    58             {
    59                 pre[v]=u;
    60                 dist[v]=dist[u]+cost;
    61                 que.push(node(v,dist[v]));
    62             }
    63         }
    64     }
    65 }
    66 
    67 int main()
    68 {
    69     int m,h=0;
    70     char s1[10],s2[10];
    71     while ( scanf("%d",&m)!=EOF && m!=-1 )
    72     {
    73         for ( int i=0;i<=n;i++ ) E[i].clear();
    74         for ( int i=1;i<=m;i++ )
    75         {
    76             int u,v;
    77             scanf("%s%s",s1,s2);
    78             u=s1[0];
    79             v=s2[0];
    80             addedge(v,u);
    81             addedge(u,v);
    82         }
    83         scanf("%lld%s%s",&num,s1,s2);
    84         e=s1[0];
    85         s=s2[0];
    86         dij();
    87         printf("Case %d:
    %lld
    ",++h,dist[e]);
    88         while ( e!=s )
    89         {
    90             printf("%c-",e);
    91             e=pre[e];
    92         }
    93         printf("%c
    ",s);
    94     }
    95     return 0;
    96 }
    UVA10537

    7.(UVA11090)https://vjudge.net/problem/UVA-11090

    题意:给定一个n个点和m条边的加权有向图,求平均权值最小的回路。

    分析:二分+SPFA判负环,首先二分平均值,在进行一次SPFA判断有无负环的存在。在SPFA过程中,因为起初没有起点,所有需要将所有点都存入队列中

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 #include<cmath>
     7 using namespace std;
     8 const double eps=1e-6;
     9 const int maxn=60;
    10 const int inf=1e9;
    11 struct Edge{
    12     int v;
    13     double cost;
    14     Edge(int _v=0,double _cost=0):v(_v),cost(_cost) {}
    15 }; 
    16 vector<Edge>E[maxn];
    17 bool vis[maxn];
    18 int cnt[maxn];
    19 double dist[maxn];
    20 int n;
    21 
    22 void addedge(int u,int v,double w)
    23 {
    24     E[u].push_back(Edge(v,w));
    25 }
    26 
    27 bool spfa(double m)
    28 {
    29     queue<int>que;
    30     while ( !que.empty() ) que.pop();
    31     for ( int i=1;i<=n;i++ )
    32     {
    33         dist[i]=0;
    34         que.push(i);
    35         vis[i]=true;
    36         cnt[i]=1;
    37     }
    38     while ( !que.empty() )
    39     {
    40         int u=que.front();
    41         que.pop();
    42         vis[u]=false;
    43         for ( int i=0;i<E[u].size();i++ )
    44         {
    45             int v=E[u][i].v;
    46             double cost=E[u][i].cost-m;
    47             if ( dist[v]>dist[u]+cost )
    48             {
    49                 dist[v]=dist[u]+cost;
    50                 if ( !vis[v] )
    51                 {
    52                     vis[v]=true;
    53                     que.push(v);
    54                     if ( ++cnt[v]>n ) return false;    
    55                 }    
    56             }
    57         }
    58     }
    59     return true;
    60 }
    61 
    62 int main()
    63 {
    64     int T,m;
    65     double l,r,mid;
    66     scanf("%d",&T);
    67     for ( int h=1;h<=T;h++ )
    68     {
    69         scanf("%d%d",&n,&m);
    70         for ( int i=1;i<=n;i++ ) E[i].clear();
    71         for ( int i=1;i<=m;i++ )
    72         {
    73             int u,v;
    74             double w;
    75             scanf("%d%d%lf",&u,&v,&w);
    76             addedge(u,v,w);
    77         }
    78         printf("Case #%d: ",h);
    79         l=0,r=10000000;
    80         while ( r-l>eps )
    81         {
    82             mid=(l+r)/2;
    83             if ( spfa(mid) ) l=mid;
    84             else r=mid;
    85         }
    86         if ( abs(l-1e7)<eps ) printf("No cycle found.
    ");
    87         else printf("%.2lf
    ",l);
    88     }
    89     return 0;
    90 }
    UVA11090

    8.(UVA11478)https://vjudge.net/problem/UVA-11478

    题意:给定一个有向图,每条边有一个权值。每次可以选择一个节点u和一个整数d,把所有以u为终点的边的权值减小d,把所有以u为起点的边的权值增加d,最后要让所有边权中的最小值非负且尽量大

    分析:注意不同的操作之间互不影响,因此可以按任意顺序实施这些操作。另外对于同一个点的多次操作也可以合并。因此可以设置sum(u)表示所有在结点u上进行的操作。二分答案x,对于边(a,b)来说可以得到sum(b)-sum(a)<=w(a,b) -x,这样就转化为差分约束系统了。当出现负环时表示不存在该答案。判断二分的左右区间,若右边界的答案存在则值无限,若左边界的答案不存在则值不存在

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=510;
     8 const int inf=1e4;
     9 struct edge{
    10     int v,cost;
    11     edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
    12 };
    13 vector<edge>E[maxn];
    14 bool vis[maxn];
    15 int cnt[maxn],dist[maxn],s,n;
    16 bool flag;
    17 
    18 void addedge(int u,int v,int w)
    19 {
    20     E[u].push_back(edge(v,w));
    21 }
    22 
    23 bool SPFA(int mid)
    24 {
    25     memset(vis,false,sizeof(vis));
    26     memset(cnt,0,sizeof(cnt));
    27     for ( int i=0;i<=n;i++ ) dist[i]=inf;
    28     vis[s]=true;
    29     dist[s]=0;
    30     queue<int>que;
    31     que.push(s);
    32     cnt[s]=1;
    33     while ( !que.empty() ) {
    34         int u=que.front();
    35         que.pop();
    36         vis[u]=false;
    37         for ( int i=0;i<E[u].size();i++ ) {
    38             int v=E[u][i].v;
    39             int cost;
    40             cost=E[u][i].cost-mid;
    41             if ( dist[v]>dist[u]+cost ) {
    42                 dist[v]=dist[u]+cost;
    43                 if ( !vis[v] ) {
    44                     vis[v]=true;
    45                     que.push(v);
    46                     if ( ++cnt[v]>(n+1) ) return false;
    47                 }
    48             }
    49         }
    50     }
    51     return true;
    52 }
    53 
    54 bool judge(int mid)
    55 {
    56     bool ok=SPFA(mid);
    57     if ( ok ) return flag=true;
    58     return false;
    59 }
    60 
    61 int main()
    62 {
    63     int m,l,r,mid;
    64     while ( scanf("%d%d",&n,&m)!=EOF )
    65     {
    66         flag=false;
    67         for ( int i=0;i<=n;i++ ) E[i].clear();
    68         s=0;
    69         for ( int i=1;i<=n;i++ ) addedge(s,i,0);
    70         for ( int i=1;i<=m;i++ )
    71         {
    72             int u,v,w;
    73             scanf("%d%d%d",&u,&v,&w);
    74             addedge(u,v,w);
    75         }
    76         l=1;
    77         r=inf;
    78         if ( judge(r) ) printf("Infinite
    ");
    79         else if ( !judge(l) ) printf("No Solution
    ");
    80         else
    81         {
    82             while ( r-l>1 )
    83             {
    84                 mid=(l+r)/2;
    85                 if ( judge(mid) ) l=mid;
    86                 else r=mid;
    87             }
    88             printf("%d
    ",l);    
    89         }
    90     }
    91     return 0;
    92 }
    UVA11478

    9.(POJ3255)http://poj.org/problem?id=3255

    题意:求次短路

    分析:次短路模板题

     1 #include<cstdio> 
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=1e4+10;
     8 const int inf=1e9;
     9 struct node{
    10     int v;
    11     int c;
    12     node(int _v=0,int _c=0):v(_v),c(_c) {}
    13     bool operator < (const node &r)const{
    14     return c>r.c;
    15     }
    16 };
    17 struct Edge{
    18     int v,cost;
    19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
    20 };
    21 vector<Edge>E[maxn];
    22 bool vis[maxn];
    23 int dist[2][maxn];
    24 int n,s;
    25 
    26 void addedge(int u,int v,int w)
    27 {
    28     E[u].push_back(Edge(v,w));
    29 }
    30 
    31 void dij()
    32 {
    33     for ( int i=1;i<=n;i++ ) 
    34     {
    35         dist[0][i]=inf;
    36         dist[1][i]=inf;
    37     }
    38     priority_queue<node>que;
    39     while ( !que.empty() ) que.pop();
    40     dist[0][s]=0;
    41     que.push(node(s,0));
    42     node tmp;
    43     while ( !que.empty() )
    44     {
    45         tmp=que.top();
    46         que.pop();
    47         int u=tmp.v;
    48         if ( dist[1][u]<tmp.c ) continue;
    49         for ( int i=0;i<E[u].size();i++ )
    50         {
    51             int v=E[u][i].v;
    52             int cost=E[u][i].cost;
    53             int d2=tmp.c+cost;
    54             if ( dist[0][v]>d2 )
    55             {
    56                 swap(dist[0][v],d2);
    57                 que.push(node(v,dist[0][v]));
    58             }
    59             if ( dist[1][v]>d2 && dist[0][v]<d2 )
    60             {
    61                 dist[1][v]=d2;
    62                 que.push(node(v,dist[1][v]));
    63             }
    64         }
    65     }
    66 }
    67 
    68 int main()
    69 {
    70     int m;
    71     while ( scanf("%d%d",&n,&m)!=EOF )
    72     {
    73         for ( int i=1;i<=n;i++ ) E[i].clear();
    74         for ( int i=1;i<=m;i++ )
    75         {
    76             int u,v,w;
    77             scanf("%d%d%d",&u,&v,&w);
    78             addedge(u,v,w);
    79             addedge(v,u,w);
    80         }
    81         s=1;
    82         dij();
    83         printf("%d
    ",dist[1][n]);
    84     }
    85     return 0;
    86 }
    POJ3255(次短路模板题)

    10.(luoguP2371)https://www.luogu.org/problemnew/show/P2371

    分析:同余最短路。(给定一些数去求一个更大的数是否可能由这些数组成)

    首先求出n=min{ai},若x能被凑出,则x+mn也能被凑出。

    建n个点(0到n-1),dis[i]分别表示模mn意义下余i的能凑出的数最小为多少。

    对于每一个ai,从x向(x+ai)%mn连一条边权为ai的边。

    求最短路,则最后求得dis[i],计算一下就可以了。

     1 #include<cstdio> 
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 typedef long long ll;
     8 const int maxN=15;
     9 const int maxn=5e5+10;
    10 const ll inf=1e18;
    11 struct node{
    12     int v;
    13     ll c;
    14     node(int _v=0,ll _c=0):v(_v),c(_c) {}
    15     bool operator < (const node &r)const{
    16     return c>r.c;
    17     }
    18 };
    19 struct Edge{
    20     int v;
    21     ll cost;
    22     Edge(int _v=0,ll _cost=0):v(_v),cost(_cost) {}
    23 };
    24 vector<Edge>E[maxn];
    25 bool vis[maxn];
    26 ll dist[maxn];
    27 int n,s;
    28 int a[maxN];
    29 
    30 void addedge(int u,int v,ll w)
    31 {
    32     E[u].push_back(Edge(v,w));
    33 }
    34 
    35 void dij()
    36 {
    37     for ( int i=0;i<n;i++ ) dist[i]=inf,vis[i]=false;
    38     priority_queue<node>que;
    39     while ( !que.empty() ) que.pop();
    40     dist[s]=0;
    41     que.push(node(s,0));
    42     node tmp;
    43     while ( !que.empty() )
    44     {
    45         tmp=que.top();
    46         que.pop();
    47         int u=tmp.v;
    48         if ( vis[u] ) continue;
    49         vis[u]=true;
    50         for ( int i=0;i<E[u].size();i++ )
    51         {
    52             int v=E[u][i].v;
    53             if ( vis[v] ) continue;
    54             ll cost=E[u][i].cost;
    55             if ( dist[v]>dist[u]+cost )
    56             {
    57                 dist[v]=dist[u]+cost;
    58                 que.push(node(v,dist[v]));
    59             }
    60         }
    61     }
    62 }
    63 
    64 int main()
    65 {
    66     int N;
    67     ll L,R,ans;
    68     while ( scanf("%d%lld%lld",&N,&L,&R)!=EOF )
    69     {
    70         for ( int i=1;i<=N;i++ ) scanf("%d",&a[i]);
    71         sort(a+1,a+1+N);
    72         n=a[1];
    73         for ( int i=0;i<n;i++ ) E[i].clear();
    74         s=0;
    75         for ( int i=0;i<n;i++ )
    76         {
    77             for ( int j=2;j<=N;j++ ) 
    78             {
    79                 if ( (a[j]+i)%n!=0 ) addedge(i,(a[j]+i)%n,1ll*a[j]);
    80             }
    81         }
    82         ans=0;
    83         dij();
    84         L--;
    85         for ( int i=0;i<n;i++ )
    86         {
    87             if ( dist[i]<=L ) ans-=(L-dist[i])/n+1;
    88             if ( dist[i]<=R ) ans+=(R-dist[i])/n+1;
    89         }
    90         printf("%lld
    ",ans);
    91     }
    92     return 0;
    93 }
    P2371

    11.(luoguP2662)https://www.luogu.org/problemnew/show/P2662

    分析:同余最短路,将所有可能出现的长度加入c[]数组,取出最小的作为n,剩余的按照上一题的方式建边。最后的答案应该为ans=max(dist[i]-n),即某一同余类中最大的不能组成数的大小。若ans为初始值0,则不存在最大值,输出-1

    注意:最后的答案计算的方式

     1 #include<cstdio> 
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=3e3+10;
     8 const int inf=1e9;
     9 struct node{
    10     int v;
    11     int c;
    12     node(int _v=0,int _c=0):v(_v),c(_c) {}
    13     bool operator < (const node &r)const{
    14     return c>r.c;
    15     }
    16 };
    17 struct Edge{
    18     int v,cost;
    19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
    20 };
    21 vector<Edge>E[maxn];
    22 bool vis[maxn],b[maxn];
    23 int dist[maxn];
    24 int n,s;
    25 int a[maxn],c[maxn];
    26 
    27 void addedge(int u,int v,int w)
    28 {
    29     E[u].push_back(Edge(v,w));
    30 }
    31 
    32 void dij()
    33 {
    34     memset(vis,false,sizeof(vis));
    35     for ( int i=0;i<n;i++ ) dist[i]=inf;
    36     priority_queue<node>que;
    37     while ( !que.empty() ) que.pop();
    38     dist[s]=0;
    39     que.push(node(s,0));
    40     node tmp;
    41     while ( !que.empty() )
    42     {
    43         tmp=que.top();
    44         que.pop();
    45         int u=tmp.v;
    46         if ( vis[u] ) continue;
    47         vis[u]=true;
    48         for ( int i=0;i<E[u].size();i++ )
    49         {
    50             int v=E[u][i].v;
    51             int cost=E[u][i].cost;
    52             if ( !vis[v] && dist[v]>dist[u]+cost )
    53             {
    54                 dist[v]=dist[u]+cost;
    55                 que.push(node(v,dist[v]));
    56             }
    57         }
    58     }
    59 }
    60 
    61 int main()
    62 {
    63     int N,M,m,ans;
    64     while ( scanf("%d%d",&N,&M)!=EOF )
    65     {
    66         memset(b,false,sizeof(b));
    67         for ( int i=1;i<=N;i++ ) 
    68         {
    69             scanf("%d",&a[i]);
    70             b[a[i]]=true;
    71             for ( int j=a[i]-1;j>=a[i]-M&&j>0;j-- ) b[j]=true;
    72         }
    73         m=0;
    74         for ( int i=1;i<=3000;i++ )
    75         {
    76             if ( b[i] ) c[++m]=i;
    77         }
    78         n=c[1];
    79         for ( int i=0;i<n;i++ ) E[i].clear();
    80         for ( int i=0;i<n;i++ )
    81         {
    82             for ( int j=2;j<=m;j++ )
    83             {
    84                 if ( (i+c[j])%n!=0 ) addedge(i,(i+c[j])%n,c[j]);
    85             }
    86         }
    87         s=0;
    88         dij();
    89         ans=0;
    90         for ( int i=0;i<n;i++ ) 
    91         {
    92             if ( dist[i]!=inf ) ans=max(ans,dist[i]-n);
    93         }
    94         if ( ans!=0 ) printf("%d
    ",ans);
    95         else printf("-1
    ");
    96     }
    97     return 0;
    98 }
    P2662

    12.(HDOJ3873)http://acm.hdu.edu.cn/showproblem.php?pid=3873

     题意:有一个n个点和m条边的有向图,起点为1,终点为n,对于第i个点来说会被in[i]个点所保护,只有先到那些保护它的点后才能到该点(可以同时有多支队伍)。求到达终点的最短时间

    分析:dij的变形,设置in[i]为保护i的点还有in[i]个,val[i]为到达所有保护点i的点需要的最少的时间.每次访问点u时将它保护的点v进行更新数组in[v]和val[v],当in[v]==0&&dist[v]!=inf时,点v可以入队

      1 #include<cstdio> 
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<queue>
      6 using namespace std;
      7 const int maxn=1e6+10;
      8 const int inf=1e9;
      9 struct node{
     10     int v;
     11     int c;
     12     node(int _v=0,int _c=0):v(_v),c(_c) {}
     13     bool operator < (const node &r)const{
     14     return c>r.c;
     15     }
     16 };
     17 struct Edge{
     18     int v,cost;
     19     Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
     20 };
     21 vector<Edge>E[maxn];
     22 vector<int>G[maxn];
     23 bool vis[maxn];
     24 int dist[maxn],in[maxn],val[maxn];
     25 int n,s;
     26 
     27 void addedge(int u,int v,int w)
     28 {
     29     E[u].push_back(Edge(v,w));
     30 }
     31 
     32 void dij()
     33 {
     34     memset(vis,false,sizeof(vis));
     35     for ( int i=1;i<=n;i++ ) dist[i]=inf;
     36     priority_queue<node>que;
     37     while ( !que.empty() ) que.pop();
     38     dist[s]=0;
     39     que.push(node(s,0));
     40     node tmp;
     41     while ( !que.empty() )
     42     {
     43         tmp=que.top();
     44         que.pop();
     45         int u=tmp.v;
     46         if ( vis[u] ) continue;
     47         vis[u]=true;
     48         for ( int i=0;i<G[u].size();i++ )
     49         {
     50             int v=G[u][i];
     51             in[v]--;
     52             val[v]=max(val[v],dist[u]);
     53             if ( dist[v]!=inf && !in[v] )
     54             {
     55                 dist[v]=max(dist[v],val[v]);
     56                 que.push(node(v,dist[v]));
     57             }
     58         }
     59         for ( int i=0;i<E[u].size();i++ )
     60         {
     61             int v=E[u][i].v;
     62             if ( vis[v] ) continue;
     63             int cost=E[u][i].cost;
     64             if ( dist[v]>cost+dist[u] )
     65             {
     66                 dist[v]=cost+dist[u];
     67                 if ( !in[v] ) que.push(node(v,dist[v]));
     68             }
     69         }
     70     }
     71 }
     72 
     73 int main()
     74 {
     75     int T,m;
     76     scanf("%d",&T);
     77     while ( T-- )
     78     {
     79         scanf("%d%d",&n,&m);
     80         s=1;
     81         for ( int i=1;i<=n;i++ ) 
     82         {
     83             E[i].clear();
     84             G[i].clear();
     85             val[i]=0;
     86         }
     87         for ( int i=1;i<=m;i++ )
     88         {
     89             int u,v,w;
     90             scanf("%d%d%d",&u,&v,&w);
     91             addedge(u,v,w);
     92         }
     93         for ( int i=1;i<=n;i++ )
     94         {
     95             scanf("%d",&in[i]);
     96             for ( int j=1;j<=in[i];j++ )
     97             {
     98                 int x;
     99                 scanf("%d",&x);
    100                 G[x].push_back(i);
    101             }
    102         }
    103         dij();
    104         printf("%d
    ",dist[n]);
    105     }
    106     return 0;
    107 }
    HDOJ3873

    13.(HDOJ4845)http://acm.hdu.edu.cn/showproblem.php?pid=4845

    分析:状态压缩+DFS,利用分层思想建立模型,用二进制代表所拿到的钥匙(状态),不同的状态对应不同的图。

    设置数组dp[i][j][k]表示从(1,1,0)到(i,j,k)(横坐标为x,纵坐标为y,状态为k)需要的步数,vis[i][j][k]代表有无访问过。key[i][j]代表坐标(i,j)所包含的钥匙状态,从(1,1,0)开始跑BFS即可

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 using namespace std;
     6 const int maxn=18;
     7 const int maxm=12;
     8 const int inf=1e9;
     9 struct node{
    10     int x,y,sta;
    11     node(int _x=0,int _y=0,int _sta=0):x(_x),y(_y),sta(_sta) {}
    12 };
    13 int door[maxn][maxn][maxn][maxn];
    14 int key[maxn][maxn],dp[maxn][maxn][1<<maxm];
    15 bool vis[maxn][maxn][1<<maxm];
    16 int n,m,p,s;
    17 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    18 
    19 void BFS()
    20 {
    21     memset(vis,false,sizeof(vis));
    22     for ( int i=1;i<=n;i++ )
    23     {
    24         for ( int j=1;j<=m;j++ )
    25         {
    26             for ( int k=0;k<1<<(s+1);k++ ) dp[i][j][k]=inf;
    27         }
    28     }
    29     dp[1][1][0]=0;
    30     vis[1][1][0]=0;
    31     queue<node>que;
    32     que.push(node(1,1,0));
    33     while ( !que.empty() )
    34     {
    35         node tmp=que.front();
    36         que.pop();
    37         int x=tmp.x,y=tmp.y,sta=tmp.sta;
    38         if ( x==n && y==m ) return;
    39         for ( int i=0;i<4;i++ )
    40         {
    41             int fx=x+dir[i][0];
    42             int fy=y+dir[i][1];
    43             int h=door[x][y][fx][fy];
    44             int sta_=sta|key[fx][fy];
    45             int t;
    46             if ( h!=-1 ) t=sta&(1<<h);
    47             if ( h==0 || (h!=-1 && t==0) ) continue;
    48             if ( fx<=0 || fx>n || fy<=0 || fy>m || vis[fx][fy][sta_] ) continue;
    49             vis[fx][fy][sta_]=true;
    50             que.push(node(fx,fy,sta_));
    51             dp[fx][fy][sta_]=dp[x][y][sta]+1;
    52         }
    53     }
    54     return;
    55 }
    56 
    57 int main()
    58 {
    59     int k,ans;
    60     while ( scanf("%d%d%d",&n,&m,&p)!=EOF )
    61     {
    62         memset(door,-1,sizeof(door));
    63         memset(key,0,sizeof(key));
    64         scanf("%d",&k);
    65         for ( int i=1;i<=k;i++ )
    66         {
    67             int x1,x2,y1,y2,g;
    68             scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
    69             door[x1][y1][x2][y2]=door[x2][y2][x1][y1]=g;
    70         }
    71         scanf("%d",&s);
    72         for ( int i=1;i<=s;i++ )
    73         {
    74             int x,y,g;
    75             scanf("%d%d%d",&x,&y,&g);
    76             key[x][y]|=(1<<g);
    77         }
    78         BFS();
    79         ans=-1;
    80         for ( int i=0;i<1<<(s+1);i++ )
    81         {
    82             if ( dp[n][m][i]!=inf ) ans=dp[n][m][i];
    83         }
    84         if ( ans==inf ) printf("-1
    ");
    85         else printf("%d
    ",ans);
    86     }
    87     return 0;
    88 }
    HDOJ4845
  • 相关阅读:
    linux下RTP编程(使用JRTPLIB)(转)
    omap 移植qt4.7.0
    mknod指令详解
    mplayer 在线播放错误
    移植Mplayer到OK6410开发板
    海量数据处理算法—Bit-Map
    海量数据面试题----分而治之/hash映射 + hash统计 + 堆/快速/归并排序
    并行、并发、同步和互斥
    阿里巴巴集团2014年校园招聘北京笔试题
    动态规划之矩阵连乘
  • 原文地址:https://www.cnblogs.com/HDUjackyan/p/9340560.html
Copyright © 2020-2023  润新知