原题链接:http://pat.zju.edu.cn/contests/pat-a-practise/1018
本题实现中注意菱形路径的处理
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX=501;
#define INF 0x7f7f7f7f
struct linkinfo
{
vector<int> li;
};
struct jilu
{
int take;
int back;
vector<int> road;
};
jilu mx;
int numbers[MAX];
int graph[MAX][MAX];
linkinfo pres[MAX];
linkinfo nexts[MAX];
int Dijstra(int n, int sp)
{
bool used[MAX];
vector<int> miv;
int min = INF, dist[MAX];
memset(used,false,sizeof(used));
for(int i=0;i<=n;i++)
{
dist[i] = graph[0][i];
}
while(!used[sp])
{
min = INF;
miv.clear();
for(int i=0; i<=n; i++)
{
if(!used[i])
{
if(min>dist[i])
{
min = dist[i];
miv.clear();
miv.push_back(i);
}
else if(min == dist[i])
{
min = dist[i];
miv.push_back(i);
}
}
}
for(auto iter=miv.begin(); iter!=miv.end(); iter++)
{
used[*iter] = true;
for(int j=1; j<=n; j++)
{
if(j != *iter && dist[*iter] + graph[*iter][j] <= dist[j])
{
if(dist[*iter] + graph[*iter][j] < dist[j])
{
dist[j] = graph[0][j] = graph[j][0] = dist[*iter] + graph[*iter][j];
pres[j].li.clear();
}
pres[j].li.push_back(*iter);
}
}
}
}
return 1;
}
bool flag[MAX];
void pre2next(int p)
{
if(!flag[p])
{
for(auto iter=pres[p].li.begin(); iter!=pres[p].li.end(); iter++)
{
nexts[*iter].li.push_back(p);
pre2next(*iter);
}
flag[p] = true;
}
}
jilu ditui(vector<int> a,int send,int all,int c,int p,int e)
{
jilu min;
min.back = INF;
min.take = INF;
int u = send+all-(a.size()-1)*c/2;
if(u+numbers[p]<c/2 && p!=0)
{
send+=c/2-u-numbers[p];
}
if(send>mx.take)
{
return min;
}
a.push_back(p);
all+=numbers[p];
if(p==e)
{
min.take = send;
min.back = send+all-(a.size()-1)*c/2;
min.road = a;
if(mx.take>min.take || (mx.take==min.take && mx.back>min.back))
{
mx = min;
}
return min;
}
for(auto iter=nexts[p].li.begin(); iter!=nexts[p].li.end(); iter++)
{
jilu tmp = ditui(a,send,all,c,*iter,e);
if(min.take>tmp.take || (min.take==tmp.take && min.back>tmp.back))
{
min = tmp;
}
}
return min;
}
int main()
{
int c,n,s,m;
memset(graph,0x7f,sizeof(graph));
scanf("%d %d %d %d",&c,&n,&s,&m);
graph[0][0] = 0;
for(int i=1;i<=n;i++)
{
scanf("%d",&numbers[i]);
graph[i][i] = 0;
}
for(int j=0,a,b;j<m;j++)
{
scanf("%d %d",&a,&b);
scanf("%d",&graph[a][b]);
graph[b][a] = graph[a][b];
}
Dijstra(n,s);
mx.back = INF;
mx.take = INF;
pre2next(s);
jilu best = ditui(vector<int>(),0,0,c,0,s);
auto iter = best.road.begin();
printf("%d %d",best.take,*iter);
iter++;
for(iter;iter!=best.road.end();iter++)
{
printf("->%d",*iter);
}
printf(" %d\n",best.back);
system("pause");
}