天天看点

1003 Emergency (25 分)

方法一:暴力回溯法

// 甲级pat1003(图,未完成).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include<vector>
#include<map>
using namespace std;


struct target_city
{
	int id;
	int road_distance;
};
int shortest_paths_variety= 0, max_helper=0, 
initial_city, final_city,shortest_distance= 2147483647;
vector<int>helper_num;
void MyInsert(map<int, vector<target_city>>&mp, 
	int start_city, target_city tempstruct);
void find(map<int, vector<target_city>>&mp,int current_city,vector<bool>visited,
	int current_distance,int current_helper);



int main()
{
	vector<bool>visited_template;
	map<int, vector<target_city>>mp;
	//<city_id,neiboring_cities>
	int city_num, road_num;
	cin >> city_num >> road_num >> initial_city >> final_city;
	for (int i = 0; i < city_num; i++)
		visited_template.push_back(false);//initialize visited
	visited_template[initial_city] = true;
	for (int i = 0; i < city_num; i++)
	{
		int temp;
		cin >> temp;
		helper_num.push_back(temp);
	}//scan helper num

	for (int i = 1; i <= road_num; i++)
	{
		int start_city,end_city;
		target_city tempstruct;
		cin >> start_city >> end_city >> tempstruct.road_distance;
		tempstruct.id = end_city;
		MyInsert(mp, start_city, tempstruct);
		tempstruct.id = start_city;
		MyInsert(mp, end_city, tempstruct);
	}//build map
	if (city_num == 1)
	{
		cout << 1 << " " << helper_num[0] + helper_num[1];
			return 0;
	}
	//find
	find(mp,initial_city,visited_template,0,0);
	cout << shortest_paths_variety << " " << max_helper;
	system("pause");
	return 0;
}

void MyInsert(map<int, vector<target_city>>&mp, int start_city, target_city tempstruct)
{
	auto item = mp.find(start_city);
	if (item == mp.end())
	{
		vector<target_city>vec;
		vec.push_back(tempstruct);
		mp.insert(pair<int, vector<target_city>>(start_city, vec));
	}
	else
	{
		item->second.push_back(tempstruct);
	}
	return;
}



void find(map<int, vector<target_city>>&mp, int current_city, vector<bool>visited,
	int current_distance, int current_helper)
{
	/*
	mp<current_city,vector<target_city>>
	vector<target_city> <=>target_city[city_num]
	target_city<=>id,road_distance
	*/
	if (current_city == initial_city)
		current_helper += helper_num[initial_city];
	auto vec = mp[current_city];
	for (auto item = vec.begin(); item != vec.end(); item++)
	{
		if (item->id == final_city)//结束
		{
			current_distance += item->road_distance;
			current_helper += helper_num[final_city];
			if (current_distance < shortest_distance)
			{
				shortest_paths_variety = 1;
				shortest_distance = current_distance;
				max_helper = current_helper;
				return;
			}
			if (current_distance > shortest_distance)
				return;
			if (current_distance == shortest_distance)
			{
				shortest_paths_variety++;
				if (current_helper > max_helper)
					max_helper = current_helper;
				return;
			}
		}
		if (!visited[item->id])
		{
			auto visitedcpy = visited;
			visitedcpy[item->id] = true;
			//current_distance += item->road_distance;
			//current_city = item->id;
			//current_helper += helper_num[item->id];
			find(mp, item->id, visitedcpy, current_distance+ item->road_distance, current_helper+ helper_num[item->id]);
		}
	}
	return;
}
           

方法二:常规Dijkstra算法

#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 501
#define INF 0x3f3f3f3f

int city_num,road_num,start_city,end_city;
int people[MAX],edge[MAX][MAX];

pair<int,int>Dijkastra()
{
	
	int dist[MAX],max_people[MAX],road_variety[MAX],vis[MAX];
	fill_n(dist,MAX,INF);
	fill_n(max_people,MAX,0);
	fill_n(road_variety,MAX,0);
	fill_n(vis,MAX,false);
	dist[start_city]=0;
	max_people[start_city]=people[start_city];
	road_variety[start_city]=1;
	
	
	for(int i=0;i<city_num;i++)
	{
	//	print(dist,dist+city_num);
		
		int u=-1,min_dist=INF;
		for(int v=0;v<city_num;v++)
		{
			if(!vis[v]&&dist[v]<min_dist)
			{
				u=v;
				min_dist=dist[v];
			}
		}
		vis[u]=true;
		for(int v=0;v<city_num;v++)
		{
			if(vis[v]||edge[u][v]==INF)
				continue;
			if(dist[u]+edge[u][v]<dist[v])
			{
				dist[v]=dist[u]+edge[u][v];
				road_variety[v]=road_variety[u];
				max_people[v]=max_people[u]+people[v]; 
			}
			else
			if(dist[u]+edge[u][v]==dist[v])
			{
				road_variety[v]+=road_variety[u];
				max_people[v]=max(max_people[v],max_people[u]+people[v]); 
			}
		}
	}
	return make_pair(road_variety[end_city],max_people[end_city]);
	 //output road_var and max_peo
}


int main()
{
	for(auto& c:edge)
		for(auto& d:c)
			d=INF;
	cin>>city_num>>road_num>>start_city>>end_city;
	for(int i=0;i<city_num;i++)
		cin>>people[i];
	for(int i=0;i<road_num;i++)
	{
		int a,b,w;
		cin>>a>>b>>w;
		edge[a][b]=edge[b][a]=w; 
	}
	auto p=Dijkastra();
	cout<<p.first<<" "<<p.second;
	system("pause"); 
	return 0;
}
           

方法三:堆优化的Dijkstra算法

//方法二:堆优化的dijkast算法
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

#define MAX 501
#define INF 0x3f3f3f3f

int city_num,road_num,start_city,end_city;
int people[MAX];
int edge[MAX][MAX];
vector<int>mp[MAX];

pair<int,int> Dijkstra()
{
	int dist[MAX],max_people[MAX],road_variety[MAX],vis[MAX];
	fill_n(dist,MAX,INF);
	fill_n(max_people,MAX,0);
	fill_n(road_variety,MAX,0);
	fill_n(vis,MAX,false);
	dist[start_city]=0;
	max_people[start_city]=people[start_city];
	road_variety[start_city]=1;
	priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>heap;
	heap.push(make_pair(0,start_city));
	int cnt=0;
	while(cnt!=city_num)
	{
		auto top=heap.top();
		heap.pop();
		int u=top.second;
		if(vis[u])
            continue;
		vis[u]=true;
        cnt++;
		for(int i=0;i<mp[u].size();i++)
		{
			int v=mp[u][i];
			if(vis[v]||edge[u][v]==INF)
			continue;
			if(dist[u]+edge[u][v]<dist[v])
			{
				dist[v]=dist[u]+edge[u][v];
				road_variety[v]=road_variety[u];
				max_people[v]=max_people[u]+people[v];
			}
			else
			if(dist[u]+edge[u][v]==dist[v])
			{
				road_variety[v]+=road_variety[u];
				max_people[v]=max(max_people[v],max_people[u]+people[v]);
			}
			heap.push(make_pair(dist[v],v));
		}
	}
	return make_pair(road_variety[end_city],max_people[end_city]);
	//output road_var and max_peo
}

int main()
{
    cin>>city_num>>road_num>>start_city>>end_city;
	for(int i=0;i<city_num;i++)
		cin>>people[i];
	for(int i=0;i<road_num;i++)
	{
		int a,b,w;
		cin>>a>>b>>w;
		edge[a][b]=edge[b][a]=w;
		mp[a].push_back(b);
		mp[b].push_back(a);
	}
	auto p=Dijkstra();
	cout<<p.first<<" "<<p.second;
	system("pause");
	return 0;
 }
           

方法四:堆优化的Dijkstra算法+动态规划

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

#define MAX 501
#define INF 0x3f3f3f3f

int city_num,road_num,start_city,end_city;
int people[MAX];
int edge[MAX][MAX];
vector<int>mp[MAX];
vector<int>pre[MAX];

int road_variety[MAX];
int max_people[MAX];
int getRoadVariety(int cur_ind)
{
    auto& res=road_variety[cur_ind];
    if(res!=-1)
        return res;
    if(cur_ind==start_city)
        return res=1;
    else
    {
        int sum=0;
        for(auto c:pre[cur_ind])
            sum+=getRoadVariety(c);
        return res=sum;
    }
}

int getMaxPeople(int cur_ind)
{
    auto&res=max_people[cur_ind];
    if(res!=-1)
        return res;
    if(cur_ind==start_city)
        return res=people[start_city];
    else
    {
        int cur_max=-1;
        for(auto c:pre[cur_ind])
            cur_max=max(cur_max,people[cur_ind]+getMaxPeople(c));
        return res=cur_max;
    }
}

pair<int,int> Dijkstra()
{
	int dist[MAX],vis[MAX];
	fill_n(dist,MAX,INF);
	fill_n(vis,MAX,false);
	dist[start_city]=0;
	priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>heap;
	heap.push(make_pair(0,start_city));
	int cnt=0;
	while(cnt!=city_num)
	{
		auto top=heap.top();
		heap.pop();
		int u=top.second;
		if(vis[u])
            continue;
		vis[u]=true;
        cnt++;
		for(int i=0;i<mp[u].size();i++)
		{
			int v=mp[u][i];
			if(vis[v]||edge[u][v]==INF)
			continue;
			if(dist[u]+edge[u][v]<dist[v])
			{
				dist[v]=dist[u]+edge[u][v];
				pre[v].clear();
				pre[v].push_back(u);
			}
			else
			if(dist[u]+edge[u][v]==dist[v])
			{
				pre[v].push_back(u);
			}
			heap.push(make_pair(dist[v],v));
		}
	}
	return make_pair(getRoadVariety(end_city),getMaxPeople(end_city));
}

int main()
{
    fill_n(road_variety,MAX,-1);
    fill_n(max_people,MAX,-1);
    cin>>city_num>>road_num>>start_city>>end_city;
	for(int i=0;i<city_num;i++)
		cin>>people[i];
	for(int i=0;i<road_num;i++)
	{
		int a,b,w;
		cin>>a>>b>>w;
		edge[a][b]=edge[b][a]=w;
		mp[a].push_back(b);
		mp[b].push_back(a);
	}
	auto p=Dijkstra();
	cout<<p.first<<" "<<p.second;
	system("pause");
	return 0;
 }