zoukankan      html  css  js  c++  java
  • loj 1316(spfa预处理+状压dp)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27024

    题意:求0-(n-1)的经过最多的标记的点的最短路。

    思路:首先我们可以spfa预处理出起点到标记的最短距离,标记的点到终点的最短距离,然后就是状压dp了,dp[state][u]表示在该状态下到达点u的最短路径。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<vector>
      7 using namespace std;
      8 #define MAXN 555
      9 #define FILL(a,b) memset(a,b,sizeof(a))
     10 #define inf 1<<30
     11 
     12 struct Edge{
     13     int v,w;
     14     Edge(int vv,int ww):v(vv),w(ww){}
     15 };
     16 
     17 int n,m,s,bit[1<<17];
     18 int Initiate(int state)
     19 {
     20     int cnt=0;
     21     while(state){
     22         cnt+=state&1;
     23         state>>=1;
     24     }
     25     return cnt;
     26 }
     27 
     28 int dist[17][MAXN],pos[17];
     29 bool mark[MAXN];
     30 vector<Edge>g[MAXN];
     31 
     32 bool spfa(int vs,int dist[])
     33 {
     34     fill(dist,dist+n,inf);
     35     FILL(mark,false);
     36     queue<int>que;
     37     que.push(vs);
     38     dist[vs]=0;
     39     while(!que.empty()){
     40         int u=que.front();
     41         que.pop();
     42         mark[u]=false;
     43         for(int i=0;i<g[u].size();i++){
     44             int v=g[u][i].v,w=g[u][i].w;
     45             if(dist[u]+w<dist[v]){
     46                 dist[v]=dist[u]+w;
     47                 if(!mark[v]){
     48                     mark[v]=true;
     49                     que.push(v);
     50                 }
     51             }
     52         }
     53     }
     54     return dist[n-1]!=inf;
     55 }
     56 
     57 int dp[1<<17][17],ans1,ans2;
     58 void Get_Dp()
     59 {
     60     for(int i=0;i<=(1<<s);i++)
     61         for(int j=0;j<=s;j++)dp[i][j]=inf;
     62     for(int i=0;i<s;i++){
     63         int p=pos[i];
     64         spfa(p,dist[i]);
     65         dp[1<<i][i]=dist[s][p];
     66     }
     67     ans1=0;
     68     ans2=dist[s][n-1];
     69     for(int state=0;state<(1<<s);state++){
     70         int tmp=bit[state];
     71         for(int i=0;i<s;i++)if(state&(1<<i)){
     72             if(dist[i][n-1]!=inf&&dp[state][i]!=inf){
     73                 if(tmp>ans1)ans1=tmp,ans2=dp[state][i]+dist[i][n-1];
     74                 else if(tmp==ans1)ans2=min(ans2,dp[state][i]+dist[i][n-1]);
     75                 for(int j=0;j<s;j++)if(!(state&(1<<j))){
     76                     dp[state|(1<<j)][j]=min(dp[state|(1<<j)][j],dp[state][i]+dist[i][pos[j]]);
     77                 }
     78             }
     79         }
     80     }
     81     printf("%d %d
    ",ans1,ans2);
     82 }
     83 
     84 
     85 
     86 int main()
     87 {
     88     int _case,t=1;
     89     scanf("%d",&_case);
     90     for(int i=0;i<=(1<<15);i++)bit[i]=Initiate(i);
     91     while(_case--){
     92         scanf("%d%d%d",&n,&m,&s);
     93         for(int i=0;i<=n;i++)g[i].clear();
     94         for(int i=0;i<s;i++)scanf("%d",&pos[i]);
     95         while(m--){
     96             int u,v,w;
     97             scanf("%d%d%d",&u,&v,&w);
     98             g[u].push_back(Edge(v,w));
     99         }
    100         printf("Case %d: ",t++);
    101         if(!spfa(0,dist[s])){
    102             puts("Impossible");
    103             continue;
    104         }
    105         Get_Dp();
    106     }
    107     return 0;
    108 }
    View Code
  • 相关阅读:
    NumPy 字符串函数
    NumPy 位运算
    Numpy 数组操作
    最小二乘法的原理与计算
    NumPy 迭代数组
    Making AJAX Applications Crawlable
    mac, start sublime from terminal
    Speed Up Your WordPress Site
    To Support High-Density Retina Displays
    HTML5 tricks for mobile
  • 原文地址:https://www.cnblogs.com/wally/p/3362051.html
Copyright © 2011-2022 走看看