AmazingCounters.com

SGU515:Recover path 【最短路】

警告:这题卡SPFA,警告:这题卡SPFA 这不是演习

题目大意:给出一个无向图,以及一些点的序列,要找出一条最短的路径使得通过所有点,题目保证存在一条头尾都在点的序列中的最短路满足题意

思路:没有最后那个保证应该就是神题了TUT 有的话显然最后的答案是一条链,而我们要做的便是找出这条链的头尾,随便找个序列中的点跑下最短路,那么头或尾两个点离这个点一定是最远的!找到一个端点后接下来便是DP找下一个端点,记忆化搜索使得路径上包含的序列点数最多,由于题目保证存在方案,最后这条路径一定是答案

最后。。。。这题卡SPFA 这不是演习

 

  1 #include <stdio.h>
  2 #include <iostream>
  3 #include<queue>
  4 #include <string.h>
  5 #include <algorithm>
  6 #define maxn 200009
  7 using namespace std;
  8 typedef pair<int,int>pii;
  9 int head[maxn],next[maxn],point[maxn],value[maxn],now=0;
 10 int n,m,maxx=-1,po,dist[maxn],x,y,z,k,v[maxn],dp[maxn],egz[maxn];
 11 int an=0,pp[maxn],final[maxn],oo=0;
 12 int num[maxn],route[maxn];
 13 
 14 void add(int x,int y,int v,int zz)
 15 {
 16     next[++now]=head[x];
 17     head[x]=now;
 18     point[now]=y;
 19     value[now]=v;
 20     num[now]=zz;
 21 }
 22 struct cmp
 23 {
 24     bool operator()(pii a,pii b)
 25     {
 26         return a.first>b.first;
 27     }
 28 };
 29 void dijkstra(int s)
 30 {
 31     memset(dist,-1,sizeof(dist));
 32     dist[s]=0;
 33     priority_queue<pii,vector<pii>,cmp>q;
 34     q.push(make_pair(0,s));
 35     while(!q.empty())
 36     {
 37         pii u=q.top();
 38         q.pop();
 39         if(u.first>dist[u.second])continue;
 40         for(int i=head[u.second];i!=0;i=next[i])
 41         {
 42             int k=point[i];
 43             if(dist[u.second]+value[i]<dist[k] || dist[k]==-1)
 44             {
 45                 dist[k]=dist[u.second]+value[i];
 46                 q.push(make_pair(dist[k],k));
 47             }
 48         }
 49     }
 50 }
 51 /*
 52 void spfa(int s,int o)
 53 {
 54     int visit[maxn]={0};
 55     queue<int>q;
 56     for(int i=1;i<=n;i++)dist[i]=-1;
 57     dist[s]=0;
 58     visit[s]=1;
 59     q.push(s);
 60     while(!q.empty())
 61     {
 62         int u=q.front();
 63         q.pop();
 64         visit[u]=0;
 65         for(int i=head[u];i!=0;i=next[i])
 66         {
 67             int k=point[i];
 68             if(dist[u]+value[i]<dist[k]|| dist[k]==-1)
 69             {
 70                 dist[k]=dist[u]+value[i];
 71                 if(visit[k]==0)
 72                 {
 73                     visit[k]=1;
 74                     q.push(k);
 75                 }
 76             }
 77         }
 78     }
 79 }
 80 */
 81 int dfs(int s,int b)
 82 {
 83     if(dp[s]!=-1)return dp[s];
 84     int ans=0;
 85     for(int i=head[s];i!=0;i=next[i])
 86     {
 87         int u=point[i];
 88         if(dist[u]!=dist[s]+value[i])continue;
 89         int val=dfs(u,(egz[s]?b+1:b));
 90         if(val>ans)
 91         {
 92             ans=val;
 93             pp[s]=u;
 94             route[s]=num[i];
 95             if(val==k-1)break;
 96         }
 97     }
 98     return dp[s]=ans+(egz[s]==1?1:0);
 99 }
100 int main()
101 {
102     scanf("%d%d",&n,&m);
103     for(int i=1;i<=m;i++)
104     {
105         scanf("%d%d%d",&x,&y,&z);
106         add(x,y,z,i);
107         add(y,x,z,i);
108     }
109     scanf("%d",&k);
110     for(int i=1;i<=k;i++){scanf("%d",&v[i]);egz[v[i]]=1;}
111     dijkstra(v[1]);
112     for(int i=1;i<=k;i++)if(dist[v[i]]>maxx)
113     {
114         maxx=dist[v[i]];
115         po=v[i];
116     }
117     dijkstra(po);
118     memset(dp,-1,sizeof(dp));
119     dfs(po,1);
120     an=po;
121     while(pp[an]!=0)
122     {
123         final[++oo]=route[an];
124         an=pp[an];
125     }
126     printf("%d\n",oo);
127     for(int i=1;i<=oo-1;i++)printf("%d ",final[i]);
128     printf("%d",final[oo]);
129     return 0;
130 }

 

posted @ 2014-10-29 15:06  philippica  阅读(445)  评论(0编辑  收藏  举报