http://www.patest.cn/contests/pat-a-practise/1018
好好研究
首先题意理解是关键
1.只有在满或者空的条件课更新,且路径上所有点都要更新为prefect状态
2.首先选择时间最少路径,即用dij
若有相同,选择从0带出的车数量最少的路径,若仍有相同,选择走完该路径,带回到0的车数量最少的路径
10 4 4 5
4 8 9 0
0 1 1
1 2 1
1 3 2
2 3 1
3 4 1
输出应为1 0->1->2->3->4 2
解题方法仍是dij+dfs
dij中不用pre[i].push_back(i),因为这里明确指出出口就是0
路径优时,pre先清空,在加入
路径相等,加入
求优dfs模板,只是在判断最优注意理解题意(更新时用+=或-=)
void dfs(int x){
if(x==出口){
tmppath.push_back(出口);
计算tmp权值;
if(权值优于tmp权值){
权值=tmp权值;
path=tmppath;
}
tmppath.pop_back();
return;
}else{
tmppath.push_back(x);
for(int i=0;i<pre[i].size();i++){
dfs(pre[x][i]);
}
tmppath.pop_back();
}
}
#include <cstdio>
#include <vector>
#include <string.h>
#define MAX 510
using namespace std;
struct edge{
int next;
int cost;
};
vector <int> path;
vector <int> tmppath;
vector <edge> adj[MAX];
int wei[MAX];
int c,n,m,k,good;
vector <int> pre[MAX];
void dij(){
int vis[MAX];
int cost[MAX];
memset(cost,-1,sizeof(cost));
memset(vis,0,sizeof(vis));
//题目已经说明终点就是0,不需要标记出口位置
/*for(int i=0;i<n;i++){
pre[i].push_back(i);
}*/
int newp=0;
vis[newp]=1;
cost[newp]=0;
for(int i=0;i<=n;i++){
for(int j=0;j<adj[newp].size();j++){
int u=adj[newp][j].next;
int c=adj[newp][j].cost;
if(vis[u]==0 ){
if(cost[u]==-1 || cost[u]>cost[newp]+c){
cost[u]=cost[newp]+c;
pre[u].clear();
pre[u].push_back(newp);
}else if(cost[u]==cost[newp]+c){
pre[u].push_back(newp);
}
}
}
int min=123123123;
for(int j=1;j<=n;j++){
if(cost[j]<min && vis[j]==0 && cost[j]!=-1){
min=cost[j];
newp=j;
}
}
vis[newp]=1;
}
}
void dfs(int x,int &ans,int &bac){
if(x==0){
tmppath.push_back(0);
int tans=0,tbac=0;
for(int i=tmppath.size()-2;i>=0;i--){
int a=tmppath[i];
if(wei[a]>good){
//这里沿路径走过,对于过去需要,现在有也无济于事,因此不考虑tans对于tbac的影响
//下面的更新全部在原有基础上做修改,用+=或者-=
/*if(tans>0){
tans-=(wei[a]-good);
if(tans<0){
tans=0;
tbac=0-tans;
}
}else*/{
tbac+=(wei[a]-good);
//tans=0;
}
}else if(wei[a]<good){
if(tbac>0){
tbac-=(good-wei[a]);
if(tbac<0){
tans+=(0-tbac);
tbac=0;
}
}else{
tans+=(good-wei[a]);
}
}
}
if(ans>tans){
ans=tans;
bac=tbac;
path=tmppath;
}else if(ans==tans && bac>tbac){
bac=tbac;
path=tmppath;
}
tmppath.pop_back();
return;
}else{
tmppath.push_back(x);
for(int i=0;i<pre[x].size();i++){
dfs(pre[x][i],ans,bac);
}
tmppath.pop_back();
}
}
int main(){
freopen("in.txt","r",stdin);
//若用while!=EOF,应该每次初始化,但后台只是一个case
while(scanf("%d %d %d %d",&c,&n,&k,&m)!=EOF){
good=c/2;
for(int i=1;i<=n;i++){
scanf("%d",&wei[i]);
}
for(int i=0;i<m;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
edge tmp;
tmp.next=a;
tmp.cost=c;
adj[b].push_back(tmp);
tmp.next=b;
tmp.cost=c;
adj[a].push_back(tmp);
}
if(wei[k]==c || wei[k]==0){
dij();
int ans=123123123,bac=123123123;
dfs(k,ans,bac);
printf("%d ",ans);
for(int i=path.size()-1;i>=0;i--){
if(i!=0){
printf("%d->",path[i]);
}else{
printf("%d ",path[i]);
}
}
printf("%d\n",bac);
}else{
printf("0 0\n");
continue;
}
}
return 0;
}