pat 1018. Public Bike Management (dijkstra+dfs)

最短路问题,复习dijkstra和dfs

首先dijkstra求出最短路,然后dfs求出所有路径

求出路径中send最小的,再求其中back最小的


point:题设的要求是修正最短路径上的所有点,实际上必须严格遵循访问顺序修改每个点的权值(eg:要依次修改权值分别为3,10的两个点,必须send2back5而非简单地back3),亦即到达目标点sp后的回程是不能修改的。

如果错误地理解为简单地将最短路径上的所有点上的权值全部改为half-full的话,会有两个case过不了



#include<stdio.h>
#include<iostream>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
using namespace std;

int cmax,n,sp,m,longest;
const int MAX=0x7fffffff;
const int number=510;
int in[number];
int ld[number][number];
int dis[number];
int bl[number];
int pre[number];
int change[number];
stack<int> sta;
multimap<int,string> mp;
multimap<int,string> mp2;
multimap<int,string>::iterator mi;
int used[number];
int mm=MAX;
int minsum=MAX;

string itos(int num)
{
	string s="";
	if(num<10)
	{
		s=" ";
		s[0]=(num+'0');
	}
    if(num>=10&&num<=99)
	{
		s="  ";
		s[0]=(num%10+'0');
		s[1]=(num/10+'0');
	}
	if(num>=100)
	{
		s="   ";
		s[0]=(num%10+'0');
		s[1]=((num/10)%10+'0');
		s[2]=(num/100+'0');
	}
    return s;
}

void dijkstra(int start)    
{
	int min,i,u,j;	
	bl[start]=1;
	
	for(i=1; i<=n; ++i)
	{
		dis[i]=ld[start][i];
		if(dis[i] == MAX)
			pre[i] = -1;
		else
			pre[i] = start;
	}
	
    for(i=1; i<=n; i++)
	{
		min=MAX;
		u=start;
		for(j=1;j<=n;j++)
			if(dis[j]<min&&!bl[j])
			{
				min=dis[j];
				u=j;
			}
			bl[u]=1;
			for(j=1;j<=n;j++)
				if(ld[u][j]<MAX&&!bl[j])
				{
					if(dis[u]+ld[u][j]<dis[j])
					{
						dis[j]=dis[u]+ld[u][j];
						pre[j]=u;
					}
				}
	}
}

void display()
{
    stack<int> stmp=sta,stmp2;
	int x=0,sum=0,store=0;
	string str="";
	while(!stmp.empty())
	{
		x=stmp.top();
		stmp.pop();
		if(x==0)
			break;
		str+=itos(x);
		str+=">-";
		stmp2.push(change[x]);
	}
	
	while(!stmp2.empty())
	{
		x=stmp2.top();
		stmp2.pop();
		
		if(x>=0) 
		{
			store+=x; 
		}
		else
		{
			if(-x<=store)
			{
				store+=x;
			}
			else
			{ 
				sum+=(-x-store);
				store=0;
			}
			
		}
	}
	
	str+="0";
	reverse(str.begin(),str.end());
	
    if(sum>0)
	{
		if(sum==minsum)
		{
			mp.insert(make_pair(store,str));
		}
		if(sum<minsum)
		{
			mp.clear();
			mp.insert(make_pair(store,str));
			minsum=sum;
		}
		
	}
	else mp2.insert(make_pair(store,str)); 
	
}

void dfs(int start,int l)
{
	int rd=0,i,u;
	sta.push(start);
	
	if(l>longest) 
	{
		sta.pop();
		return; 
	}
	
	if(start==sp&&l==longest)
	{  
		mm=l;
		display();
		sta.pop();
		return;
	}
	
	u=start;
    for(i=1;i<=n;i++)
	{		
		if(ld[u][i]<=longest&&!used[i]&&u!=i)
		{	
			used[i]=1;
			dfs(i,l+ld[u][i]);
			used[i]=0;
		}
	}
		sta.pop();
}

int main()
{
    int i,j,s1,s2,t;
   	scanf("%d %d %d %d",&cmax,&n,&sp,&m);
	for(i=0;i<=n;i++)
		for(j=0;j<=n;j++)
			ld[i][j]=MAX;
		ld[0][0]=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&in[i]);
			ld[i][i]=0;
		}
		for(i=0;i<m;i++)
		{	
			scanf("%d %d %d",&s1,&s2,&t);
			ld[s1][s2]=t;
			ld[s2][s1]=t;
		}
		for(i=1;i<=n;i++)
		{
			change[i]=in[i]-(cmax/2);
		}
				
		dijkstra(0);
		longest=dis[sp];
		
		dfs(0,0);
			
		if(!mp2.empty())
			cout<<"0 "<<mp2.begin()->second<<" "<<mp2.begin()->first<<endl;
		else
			cout<<minsum<<" "<<mp.begin()->second<<" "<<mp.begin()->first<<endl;
		
		return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值