loj 1316(spfa预处理+状压dp)

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

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

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

loj 1316(spfa预处理+状压dp)
  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\n",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

 

你可能感兴趣的:(SPFA)