【C】最短路径--dijkstra

1003. Emergency (25)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

Input

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (<= 500) - the number of cities (and the cities are numbered from 0 to N-1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.

Output

For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather.
All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

Sample Input
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
Sample Output
2 4

#include<iostream>
using namespace std;
const int maxn=1000;
const int INF=10000000;
int n,m,c1,c2;
int d[maxn],g[maxn][maxn],w[maxn],weight[maxn],num[maxn];
int vis[maxn]={0};
void dijkstra(int s){
	fill(d,d+maxn,INF);
	fill(w,w+maxn,INF);
	int i,j,v;
	d[s]=0;
	w[s]=weight[s];
	num[s]=1;//最短路径条数 
	for(i=0;i<n;i++){
		int u=-1;
		int min=INF;
		for(j=0;j<n;j++){
			if(vis[j]==0&&d[j]<min){
				u=j;
				min=d[j];
			}
		}
		if(u==-1) return;
		vis[u]=1;
		for(v=0;v<n;v++){
			if(g[u][v]<INF&&vis[v]==0){
				if(d[v]>d[u]+g[u][v]){
					d[v]=d[u]+g[u][v];
					num[v]=num[u];//最短路径条数没有变
					w[v]=w[u]+weight[v];
				}
				else if(d[v]==d[u]+g[u][v]){
					num[v]=num[u]+num[v];
					if(w[v]<w[u]+weight[v]){
						w[v]=w[u]+weight[v];
					}
				}
			}
		}
	}
}
int main(){
	cin>>n>>m>>c1>>c2;
	int i;
	for(i=0;i<n;i++){
		cin>>weight[i];
	}
	int u,v;
	fill(g[0],g[0]+maxn*maxn,INF);
	for(i=0;i<m;i++){
		cin>>u>>v;
		cin>>g[u][v];
		g[v][u]=g[u][v];
	}
	dijkstra(c1);
	cout<<num[c2]<<" "<<w[c2]<<endl;
	return 0;
}
	

1018. Public Bike Management (30)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over the world. One may rent a bike at any station and return it to any other stations in the city.

The Public Bike Management Center (PBMC) keeps monitoring the real-time capacity of all the stations. A station is said to be in perfect condition if it is exactly half-full. If a station is full or empty, PBMC will collect or send bikes to adjust the condition of that station to perfect. And more, all the stations on the way will be adjusted as well.

When a problem station is reported, PBMC will always choose the shortest path to reach that station. If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.


Figure 1

Figure 1 illustrates an example. The stations are represented by vertices and the roads correspond to the edges. The number on an edge is the time taken to reach one end station from another. The number written inside a vertex S is the current number of bikes stored at S. Given that the maximum capacity of each station is 10. To solve the problem at S3, we have 2 different shortest paths:

1. PBMC -> S1 -> S3. In this case, 4 bikes must be sent from PBMC, because we can collect 1 bike from S1 and then take 5 bikes to S3, so that both stations will be in perfect conditions.

2. PBMC -> S2 -> S3. This path requires the same time as path 1, but only 3 bikes sent from PBMC and hence is the one that will be chosen.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 numbers: Cmax (<= 100), always an even number, is the maximum capacity of each station; N (<= 500), the total number of stations; Sp, the index of the problem station (the stations are numbered from 1 to N, and PBMC is represented by the vertex 0); and M, the number of roads. The second line contains N non-negative numbers Ci (i=1,...N) where each Ci is the current number of bikes at Si respectively. Then M lines follow, each contains 3 numbers: Si, Sj, and Tij which describe the time Tij taken to move betwen stations Si and Sj. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print your results in one line. First output the number of bikes that PBMC must send. Then after one space, output the path in the format: 0->S1->...->Sp. Finally after another space, output the number of bikes that we must take back to PBMC after the condition of Sp is adjusted to perfect.

Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC. The judge's data guarantee that such a path is unique.

Sample Input:
10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
Sample Output:
3 0->2->3 0

//给定起点,找到达指定目的地的最短路径,沿途所经的地点,点权值都要变成1/2cmax
//如果有多条路径长度一样的最短路径,就选择取走或带来点权值最小的那一条
//有陷阱在于沿途经过一个站点就要将其变成最佳
//意思是当你经过0->1->2->3时,若2多出来k个,如果1缺少x个,2多出来的k个也不能抵偿,因为1已经走过了
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn=510;//最多500个站点
const int INF=10000000;
int G[maxn][maxn];//图联通与否、每条边的权值
int weight[maxn];//记录每个点现存自行车数量
int d[maxn];//记录起点至其余各点最短路径值
int vis[maxn]={0};//是否已经被访问过
int n;//总节点数
int minneed=INF;//最少需要带来多少
int minremain=INF;//最少需要带走多少
vector<int> pre[maxn];//记录每个节点的前驱,最短前驱可能不止一个
vector<int> tempath;//临时路径
vector<int> path;//最优路径
void dijkstra(int s){
	fill(d,d+maxn,INF);
	d[s]=0;
	int i,j,v;
	for(i=0;i<n;i++){
		int u=-1;
		int min=INF;
		for(j=0;j<n;j++){
			if(vis[j]==0&&d[j]<min){
				u=j;
				min=d[j];
			}
		}
		vis[u]=1;
		for(v=0;v<=n;v++){
			if(G[u][v]<INF&&vis[v]==0&&d[v]>d[u]+G[u][v]){
				d[v]=d[u]+G[u][v];
				pre[v].clear();
				pre[v].push_back(u);//清空,更新前驱
			}
			else if(G[u][v]<INF&&vis[v]==0&&d[v]==d[u]+G[u][v]){
				pre[v].push_back(u);
			}
		}
	}
}
void dfs(int v){
	if(v==0){//遍历到了总站点
		tempath.push_back(v);
		int need=0,remain=0;//从总站点向下,初始需要携带的为0,需要带回的为0
		for(int i=tempath.size()-1;i>=0;i--){
			int id=tempath[i];//当前序号
			if(weight[id]<0){//当前站点自行车量小于最佳
				if(remain>(-1)*weight[id]){//当前携带的够给这个站点的
					remain=remain-(-1)*weight[id];
				}
				else{//不够给,还要再带点
					need=(-1)*weight[id]-remain+need;
					remain=0;//这个容易忘记!!!
				}
			}
			else if(weight[id]>0){//多了,要么need减少,要么remain增加???
				//但是这里只处理了remain
				remain=remain+weight[id];
			}
		}
		if(need<minneed){
			minneed=need;//优化
			minremain=remain;//覆盖
			path=tempath;//覆盖
		}
		else if(need==minneed&&remain<minremain){
			minremain=remain;
			path=tempath;
		}
		tempath.pop_back();
		return;
	}
	tempath.push_back(v);
	for(int i=0;i<pre[v].size();i++){
		dfs(pre[v][i]);
	}
	tempath.pop_back();
}
int main(){
	int cmax,sp,m,i;
	cin>>cmax>>n>>sp>>m;
	fill(G[0],G[0]+maxn*maxn,INF);
	int perfect=cmax/2;
	for(i=1;i<=n;i++){//注意站点序号除了总站,其余1-n
		cin>>weight[i];
		weight[i]=weight[i]-perfect;
	}
	for(i=0;i<m;i++){
		int a,b,c;
		cin>>a>>b>>c;
		G[a][b]=c;
		G[b][a]=c;
	}
	dijkstra(0);
	dfs(sp);//从目标站点开始
	cout<<minneed<<" ";
	for(i=path.size()-1;i>0;i--){
		cout<<path[i]<<"->";
	}
	cout<<path[0]<<" "<<minremain;
	return 0;
}

1030. Travel Plan (30)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (<=500) is the number of cities (and hence the cities are numbered from 0 to N-1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:

City1 City2 Distance Cost

where the numbers are all integers no more than 500, and are separated by a space.

Output Specification:

For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

Sample Input
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Sample Output
0 2 3 3 40

#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn=510;
const int INF=100000;
int G[maxn][maxn];//存储节点距离
int d[maxn];//存储当前最短距离
int weight[maxn][maxn];//存储节点cost
int w[maxn];//存储当前cost
int vis[maxn]={0};
int n;
vector<int> pre[maxn];//前驱结点
vector<int> path;
void dijkstra(int s){
	fill(d,d+maxn,INF);
	fill(w,w+maxn,INF);
	w[s]=0;
	d[s]=0;
	int i,j,v;
	for(i=0;i<n;i++){
		int u=-1;
		int min=INF;
		for(j=0;j<n;j++){
			if(vis[j]==0&&d[j]<min){
				u=j;
				min=d[j];
			}
		}
		if(u==-1) return;
		vis[u]=1;
		for(v=0;v<n;v++){
			if(vis[v]==0&&G[u][v]<INF){
				if(d[v]>d[u]+G[u][v]){
					d[v]=d[u]+G[u][v];
					w[v]=w[u]+weight[u][v];
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if(d[v]==d[u]+G[u][v]){
					if(w[v]>w[u]+weight[u][v]){
						w[v]=w[u]+weight[u][v];
						pre[v].clear();
						pre[v].push_back(u);
					}
					else if(w[v]==w[u]+weight[u][v]){
						pre[v].push_back(u);
					}
				}
			}
		}
	}
}
int main(){
	int m,s,t;
	cin>>n>>m>>s>>t;
	fill(G[0],G[0]+maxn*maxn,INF);
	int i;
	for(i=0;i<m;i++){
		int c1,c2,dis,cost;
		cin>>c1>>c2>>dis>>cost;
		G[c1][c2]=G[c2][c1]=dis;
		weight[c1][c2]=weight[c2][c1]=cost;
	}
	dijkstra(s);
	/*for(i=pre[t].size()-1;i>=0;i--){
		cout<<pre[t][i]<<" ";
	}
	cout<<d[t]<<" "<<w[t]<<endl;*/
	int tt=t;
	path.push_back(t);
	while(pre[t].size()>0){//将前驱加入path路径,然后倒序输出 
		for(i=0;i<pre[t].size();i++){
			path.push_back(pre[t][i]);
		}
		t=path.back();
	}
	for(i=path.size()-1;i>0;i--){
		printf("%d ",path[i]);
	}
	printf("%d ",path[0]);
	cout<<d[tt]<<" "<<w[tt]<<endl;
	return 0;
}

1072. Gas Station (30)

时间限制
200 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

A gas station has to be built at such a location that the minimum distance between the station and any of the residential housing is as far away as possible. However it must guarantee that all the houses are in its service range.

Now given the map of the city and several candidate locations for the gas station, you are supposed to give the best recommendation. If there are more than one solution, output the one with the smallest average distance to all the houses. If such a solution is still not unique, output the one with the smallest index number.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 positive integers: N (<= 103), the total number of houses; M (<= 10), the total number of the candidate locations for the gas stations; K (<= 104), the number of roads connecting the houses and the gas stations; and DS, the maximum service range of the gas station. It is hence assumed that all the houses are numbered from 1 to N, and all the candidate locations are numbered from G1 to GM.

Then K lines follow, each describes a road in the format
P1 P2 Dist
where P1 and P2 are the two ends of a road which can be either house numbers or gas station numbers, and Dist is the integer length of the road.

Output Specification:

For each test case, print in the first line the index number of the best location. In the next line, print the minimum and the average distances between the solution and all the houses. The numbers in a line must be separated by a space and be accurate up to 1 decimal place. If the solution does not exist, simply output “No Solution”.

Sample Input 1:
4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2
Sample Output 1:
G1
2.0 3.3
Sample Input 2:
2 1 2 10
1 G1 9
2 G1 20
Sample Output 2:
No Solution
#include<stdio.h>
#include<iostream>
#include<string>
#include<math.h>
using namespace std;
const int maxn=1020;
const int INF=100000;
int d[maxn],G[maxn][maxn];
int vis[maxn];
int can[20]={0};//参选资格
int dis[20];//每个站点的最短路径
int sum[20]={0};//总距离
int n,m,ds;
void dijkstra(int s){
	int i,j,v;
	fill(d,d+maxn,INF);
	d[s]=0;
	for(i=1;i<=n+m;i++){
		int u=-1;
		int min=INF;
		for(j=1;j<=n+m;j++){
			if(d[j]<min&&vis[j]==0){
				u=j;
				min=d[j];
			}
		}
		if(u==-1) return;
		vis[u]=1;
		for(v=1;v<=n+m;v++){
			if(G[u][v]!=INF&&vis[v]==0&&d[u]+G[u][v]<d[v]){
				d[v]=G[u][v]+d[u];
			}
		}
	}
}
int deal(string str){
	int i,a;
	int num=0;
	if(str[0]=='G'){
		for(i=1;i<str.size();i++){
			a=(int)(str[i]-'0');
			num=num+(int)pow(10.0,(double)str.size()-1-i)*a;
		}
		return n+num;
	}
	else{
		for(i=0;i<str.size();i++){
			a=(int)(str[i]-'0');
			num=num+(int)pow(10.0,(double)str.size()-1-i)*a;
		}
	}
	return num;
}
int main(){
	int k,ds,i,j;
	cin>>n>>m>>k>>ds;
	fill(G[0],G[0]+maxn*maxn,INF);
	for(i=0;i<k;i++){
		string str1,str2;
		int c;
		cin>>str1>>str2>>c;
		int a=deal(str1);
		int b=deal(str2);
		G[a][b]=c;
		G[b][a]=c;
	}
	for(i=n+1;i<=n+m;i++){
		for(j=1;j<=n+m;j++){
			vis[j]=0;
		}
		dijkstra(i);//对每一个Gi寻找最短路径
		//找最短路径中的最近距离
		int min=INF;
		int u=-1;
		/*for(j=1;j<=n;j++){
			printf("d[%d]=%d  ",j,d[j]);
		}*/
		//printf("\n");
		for(j=1;j<=n&&can[i-n]==0;j++){
			if(d[j]>ds){
				can[i-n]=1;dis[i-n]=-1;
				//printf("d[%d]=%d\n",j,d[j]);
			}
			else if(d[j]<min){
				u=j;min=d[j];
			}
			sum[i-n]=sum[i-n]+d[j];
		}
		//printf("sum[%d]=%d\n",i-n,sum[i-n]);
		if(can[i-n]==0){
			dis[i-n]=min;
			//cout<<"min="<<min<<endl;
		}
	}//每个站点的最短路径中的最短距离
	int u=-1;
	int max=-1;
	for(i=1;i<=m;i++){//求最短距离最长的那个站点
		if(can[i]==0){
			//printf("dis[%d]=%d\n",i,dis[i]);
			if(dis[i]>max){
				u=i;
				max=dis[i];
				//printf("max=%d\n",max);
			}
			else if(dis[i]==max){//最短距离相同,找平均距离小的
				int a=sum[i];
				int b=sum[u];
				//printf("sum[%d]=a=%d,sum[%d]=b=%d",i,u,a,b);
				if(a<b){
					//printf("sum[%d]=a=%d,sum[%d]=b=%d",i,u,a,b);
					u=i;
				}
				//平均距离也相同,选序号小的,先出现的u小
			}
		}
	}
	if(u==-1) cout<<"No Solution"<<endl;
	else{
		printf("G%d\n",u);
		printf("%.1f %.1f",(double)dis[u],(double)sum[u]/(double)n);
	}
	return 0;
}

1087. All Roads Lead to Rome (30)

时间限制
200 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers N (2<=N<=200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N-1 lines each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format "City1 City2 Cost". Here the name of a city is a string of 3 capital English letters, and the destination is always ROM which represents Rome.

Output Specification:

For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommended. If such a route is still not unique, then we output the one with the maximum average happiness -- it is guaranteed by the judge that such a solution exists and is unique.

Hence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommended route. Then in the next line, you are supposed to print the route in the format "City1->City2->...->ROM".

Sample Input:
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
Sample Output:
3 3 195 97
HZH->PRS->ROM
//map存储城市名及其编号
//存储最短路径的前驱
//最短路径相同时happy值高的,happy相同时,平均happy高的
//输出途径城市数(!!!题意:最短路径数)、花费、happy、平均happy
#include<stdio.h>
#include<iostream>
#include<vector>
#include <string>
#include<map>
using namespace std;
const int maxn=210;
const int INF=1000000;
int G[maxn][maxn],d[maxn];
int w[maxn],weight[maxn];
int vis[maxn]={0};
int numnow[maxn]={0};
int n;
vector<int> pre[maxn];
map<string,int> mpc;
struct CITY{
	int happy;
	string name;
}city[maxn];
void dijkstra(int s){
	int i,j,v;
	fill(d,d+maxn,INF);
	fill(w,w+maxn,INF);
	w[s]=0;
	d[s]=0;w[s]=weight[s];
	numnow[s]=1;
	for(i=0;i<n;i++){
		int u=-1;
		int min=INF;
		for(j=0;j<n;j++){
			if(vis[j]==0&&d[j]<min){
				u=j;
				min=d[j];
			}
		}
		if(u==-1) return;
		vis[u]=1;
		for(v=0;v<n;v++){
			if(vis[v]==0&&G[u][v]!=INF&&G[u][v]+d[u]<d[v]){
				numnow[v]=numnow[u];
				d[v]=G[u][v]+d[u];
				w[v]=weight[v]+w[u];
				//printf("1.d[%d]=%d,w[%d]=%d\n",v,d[v],v,w[v]);
				pre[v].clear();
				pre[v].push_back(u);
			}
			else if(vis[v]==0&&G[u][v]!=INF&&G[u][v]+d[u]==d[v]){
				numnow[v]=numnow[u]+numnow[v];
				if(w[v]<weight[v]+w[u]){
					w[v]=weight[v]+w[u];
					//printf("2.d[%d]=%d,w[%d]=%d\n",v,d[v],v,w[v]);
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if(w[v]==weight[v]+w[u]){
					int nump1=0,nump2=0;
					int vv=v,uu=u;
					while(pre[vv].size()!=0){
						nump1++;
						vv=pre[vv].front();
					}
					while(pre[uu].size()!=0){
						nump2++;
						uu=pre[uu].front();
					}
					if(nump1>nump2){//w的平均happy高
						pre[v].clear();
						pre[v].push_back(u);
						//printf("3.d[%d]=%d,w[%d]=%d\n",v,d[v],v,w[v]);
					}
				}
			}
		}
	}
}
int main(){
	int k,i,j;
	fill(G[0],G[0]+maxn*maxn,INF);
	string start;
	cin>>n>>k;
	getchar();
	cin>>start;
	mpc[start]=0;weight[0]=0;
	city[0].name=start;
	for(i=1;i<n;i++){
		string str1;
		int happy;
		cin>>str1>>happy;
		mpc[str1]=i;
		city[i].name=str1;
		city[i].happy=happy;
		weight[i]=happy;
	}
	for(i=0;i<k;i++){
		string str1,str2;
		int cost;
		cin>>str1>>str2>>cost;
		int a=mpc.find(str1)->second;
		int b=mpc.find(str2)->second;
		G[a][b]=cost;
		G[b][a]=cost;
	}
	dijkstra(0);
	int target=mpc.find("ROM")->second;
	int tt=target;
	int num=1;
	vector<int> path;
	while(pre[tt].size()!=0){
		tt=pre[tt].front();
		num++;
		path.push_back(tt);
	}
	printf("%d %d %d %d\n",numnow[target],d[target],w[target],w[target]/(num-1));
	for(i=path.size()-1;i>=0;i--){
		printf("%s->",city[path[i]].name.c_str());
	}
	printf("ROM");
	return 0;
}


还有两个codeup上的题目,但是都没有完成,问题C超时,问题D错误50%,其中问题C是dijkstra结合大数:

问题 C: 最短路径

时间限制: 1 Sec   内存限制: 32 MB
提交: 105   解决: 18
[ 提交][ 状态][ TK题库][命题人: ]

题目描述

N个城市,标号从0到N-1,M条道路,第K条道路(K从0开始)的长度为2^K,求编号为0的城市到其他城市的最短距离。

输入

第一行两个正整数N(2<=N<=100)M(M<=500),表示有N个城市,M条道路,
接下来M行两个整数,表示相连的两个城市的编号。

输出

N-1行,表示0号城市到其他城市的最短路,如果无法到达,输出-1,数值太大的以MOD 100000 的结果输出。

样例输入

4 3
0 1
1 2
2 0

样例输出

1
3
-1

//用大数实现2^k,实现大数加法,最后取大数的末5位,以下使用dijkstra
#include<stdio.h>
#include<iostream>
using namespace std;
const int maxn=110;
struct NUM{
	int d[1000];
	int len;
	NUM(){
		len=0;
	}
};
int n;
NUM dis[maxn],G[maxn][maxn];
int vis[maxn]={0};

NUM add(NUM a,NUM b){
	NUM c;
	int i,carry=0;
	for(i=0;i<a.len||i<b.len;i++){
		int temp=a.d[i]+b.d[i]+carry;
		c.d[c.len++]=temp%10;
		carry=temp/10;
	}
	if(carry!=0) c.d[c.len++]=carry;
	return c;
}
NUM muitl(NUM c,int k){//在c的基础上实现2^k
	int i;
	NUM a;
	a.len=c.len;
	while(k>1){
		int carry=0;
		for(i=0;i<a.len;i++){
			int temp=c.d[i]*2+carry;
			a.d[i]=temp%10;
			carry=temp/10;
		}
		while(carry!=0){
			a.d[a.len++]=carry%10;
			carry/=10;
		}
		c=a;
		k--;
	}
	return a;
}
void print(NUM c){
	int i;
	if(c.len<=5){
		int j=c.len-1;
		while(c.d[j]==0) j--;
		for(i=j;i>=0;i--){
			printf("%d",c.d[i]);
		}
	}
	else{
		int j=4;
		while(c.d[j]==0) j--;
		for(i=j;i>=0;i--){
			printf("%d",c.d[i]);
		}
	}
}
bool xiaoyu(NUM a,NUM b){
	if(b.d[0]==-1) return true;//无穷大设置为-1
	if(a.len<b.len) return true;
	else if(a.len>b.len) return false;
	else{
		int i;
		for(i=0;i<a.len;i++){
			if(a.d[i]>b.d[i]) return false;
		}
		return true;
	}
}
void dijkstra(int s){
	int i,j,v;
	for(i=0;i<n;i++){
		dis[i].d[0]=-1;
		dis[i].len=1;
	}
	dis[s].d[0]=0;
	for(i=0;i<n;i++){
		int u=-1;
		int flag=0;
		NUM min;
		min.d[0]=-1;min.len=1;
		for(j=0;j<n;j++){
			if(dis[j].d[0]!=-1&&vis[j]==0&&flag==0){
				u=j;
				min=dis[j];
				flag=1;
			}
			else if(dis[j].d[0]!=-1&&vis[j]==0&&flag==1){
				if(xiaoyu(dis[j],min)){
					u=j;
					min=dis[j];
				}
			}
		}
		if(u==-1) return;
		vis[u]=1;
		for(v=0;v<n;v++){
			if(G[u][v].d[0]!=-1&&vis[v]==0){
				if(xiaoyu(add(dis[u],G[u][v]),dis[v])){
					dis[v]=add(dis[u],G[u][v]);
				}
			}
		}
	}
}
int main(){
	int m,i,j;
	cin>>n>>m;
	for(i=0;i<n;i++){
		for(j=0;j<n;j++){
			if(j==i) G[i][j].d[0]=0;
			else G[i][j].d[0]=-1;
			G[i][j].len=1;
		}
	}
	NUM c;
	c.d[0]=1;c.len=1;//2^0
	for(i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		if(i==0){
			G[a][b]=c;
			G[b][a]=c;
		}
		else{
			NUM d=muitl(c,2);
			c=d;
			G[a][b]=d;
			G[b][a]=d;
		}
	}//第k条路径长度为2^k
	dijkstra(0);
	for(i=1;i<n;i++){
		print(dis[i]);
		printf("\n");
	}
	return 0;
}
/*6 8
0 1
0 3
0 4
2 3
2 5
3 4
4 5
1 3*/

问题 D: 最短路径

时间限制: 1 Sec   内存限制: 32 MB
提交: 84   解决: 15
[ 提交][ 状态][ TK题库][命题人: ]

题目描述

有n个城市m条道路(n<1000, m<10000),每条道路有个长度,请找到从起点s到终点t的最短距离和经过的城市名。

输入

输入包含多组测试数据。

每组第一行输入四个数,分别为n,m,s,t。

接下来m行,每行三个数,分别为两个城市名和距离。

输出

每组输出占两行。

第一行输出起点到终点的最短距离。

第二行输出最短路径上经过的城市名,如果有多条最短路径,输出字典序最小的那条。若不存在从起点到终点的路径,则输出“can't arrive”。

样例输入

3 3 1 3
1 3 3
1 2 1
2 3 1

样例输出

2
1 2 3
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
const int maxn=1010;
const int INF=100000000;
int d[maxn],G[maxn][maxn];
int n;
int father[maxn];
int vis[maxn]={0};
vector<int> pre[maxn];
void initial(){
	int i;
	for(i=1;i<=n;i++){
		father[i]=i;
	}
}
int findfather(int a){
	int x=a;
	while(a!=father[a]){
		a=father[a];
	}
	while(x!=a){
		int z=x;
		x=father[x];
		father[z]=a;
	}
	return a;
}
void UNION(int a,int b){
	int fa=findfather(a);
	int fb=findfather(b);
	if(fa!=fb){
		father[a]=fb;
	}
}

bool isarrived(int s,int t){
	int fs=findfather(s);
	int ft=findfather(t);
	if(fs!=ft) return false;
	else return true;
}
void dijkstra(int s){
	int i,j,v;
	fill(d,d+maxn,INF);
	d[s]=0;
	for(i=1;i<=n;i++){
		int u=-1;
		int min=INF;
		for(j=1;j<=n;j++){
			if(d[j]<min&&vis[j]==0){
				u=j;
				min=d[j];
			}
		}
		if(u==-1) return;
		vis[u]=1;
		for(v=1;v<=n;v++){
			if(vis[v]==0&&G[u][v]!=INF&&G[u][v]+d[u]<d[v]){
				d[v]=G[u][v]+d[u];
				pre[v].clear();
				pre[v].push_back(u);
			}
			else if(vis[v]==0&&G[u][v]!=INF&&G[u][v]+d[u]==d[v]){
				int k=pre[v].front();
				if(k>u){
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if(k==u) pre[v].push_back(u);
			}
		}
	}
}
int main(){
	int m,i,j,s,t;
	while(scanf("%d %d %d %d",&n,&m,&s,&t)!=EOF){
		initial();
		fill(G[0],G[0]+maxn*maxn,INF);
		for(i=0;i<m;i++){
			int a,b,c;
			cin>>a>>b>>c;
			G[a][b]=c;
			G[b][a]=c;
			UNION(a,b);
		}
		if(!isarrived(s,t)){
			printf("can't arrive\n");
		}
		else{
			dijkstra(s);
			vector<int> path;
			int tt=t;
			while(pre[t].size()!=0){
				int k=pre[t].back();
				path.push_back(k);
				t=k;
			}
			printf("%d\n",d[tt]);
			for(i=path.size()-1;i>=0;i--){
				printf("%d ",path[i]);
			}
			printf("%d\n",tt);
		}
	}
	return 0;
}// 如果有多条最短路径,输出字典序最小的那条?? 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值