PAT甲级(1016-1030)

题目列表知识点
1016 Phone Bills (25 分)结构体排序(分段处理),时间计算
1017 Queueing at Bank (25 分)结构体排序,模拟
1018 Public Bike Management (30 分)dij最短路,记录路径,dfs遍历最短路
1019 General Palindromic Number (20 分)回文数判断,数组存储(不能用字符串)
1020 Tree Traversals (25 分)后序+中序=>层序
1021 Deepest Root (25 分)DFS求连通块数量及树的最大高度
1022 Digital Library (30 分)map映射
1023 Have Fun with Numbers (20 分)模拟加法,字符串
1024 Palindromic Number (25 分)模拟加法,回文数
1025 PAT Ranking (25 分)结构体排序
1026 Table Tennis (30 分)
1027 Colors in Mars (20 分)进制转化
1028 List Sorting (25 分)简单结构体排序
1029 Median (25 分)排序,中位数
1030 Travel Plan (30 分)dij最短路,dfs输出路径

1016 Phone Bills (25 分)

题目大意:

给出长途电话的每小时计费和一系列通话记录,计算不同用户每个月的电话费。

思路:

1、结构体存储用户信息

2、按照用户名字字典序从小到大排序,并按时间从早到晚依次排序

3、因为最后要计算某用户在这个月中所有通话的总花费,所以不能仅仅只是两个两个处理(on-line和off-line匹配),需要一段一段的处理:按照用户的名字,将所有记录分段,每次统一处理同一用户的所有通话记录,处理的同时计算该用户每一次的花费;处理完成后,即可输出该用户的总花费。(样例排序后,分为三段来处理)

CYJJ 01:01:05:59 on-line
CYJJ 01:01:07:00 off-line
//
CYLL 01:01:06:01 on-line
CYLL 01:01:08:03 off-line
CYLL 01:28:15:41 on-line
CYLL 01:28:16:05 off-line
//
aaa 01:01:01:03 on-line
aaa 01:02:00:01 on-line
aaa 01:05:02:24 on-line
aaa 01:04:23:59 off-line

4、时间差计算(涉及到隔天计算)

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> p;
inline ll lowbit(ll x){return x&(-x);} 
struct stu{
	string name;
	int month,day;
	int time;
	int flag;
}s[maxn];   
int rate[24];  
bool cmp(stu a,stu b){
	if(a.name!=b.name) return a.name<b.name;
	if(a.day!=b.day) return a.day<b.day;
	return a.time<b.time;
} 
double cal(int d1,int d2,int t1,int t2){//计算时间差及花费
	int time=0;
	double ans=0;
	int h1=t1/60,m1=t1%60;
	int h2=t2/60,m2=t2%60;
	while(d1<d2||h1<h2||m1<m2){//从d1:h1:m1开始,逐渐累加时间,直至d2:h2:m2
		time++;
		ans+=rate[h1];
		m1++;
		if(m1>=60){//进位
			m1=0;
			h1++;
		}
		if(h1>=24){//进位
			d1++;
			h1=0;
		}
	}
	printf("%d $%.2lf\n",time,ans/100);
	return ans/100;
}                    
int main(){
	for(int i=0;i<24;i++){
		cin>>rate[i];
	}
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>s[i].name;
		int d,h,m;
		scanf("%d:%d:%d:%d",&s[i].month,&s[i].day,&h,&m);
		s[i].time=h*60+m;
		string t;
		cin>>t;
		if(t=="on-line") s[i].flag=true;
		else s[i].flag=false; 
	}
	sort(s,s+n,cmp);
	int now=0,next,flag;
	while(now<n){
		flag=0;
		next=now;
		while(next<n&&s[now].name==s[next].name){//分段,寻找名字相同的所有通话记录,并判断是否存在合法记录
			if(flag==0&&s[next].flag==true){
				flag=1;
			}
			if(flag==1&&s[next].flag==false) flag=2;
			next++;
		}
		if(flag<2){//没有找到合法记录,则跳过该用户,继续往下找
			now=next;
			continue;
		}
		double sum=0.0; 
		printf("%s %02d\n",s[now].name.c_str(),s[now].month);
		while(now<next){//处理某一用户的所有通话记录[now,next)
			while(now<next-1&&!(s[now].flag==true&&s[now+1].flag==false)){
				now++;
			}
			if(now==next-1){//没有找到合法记录
				now=next;
				break;
			}
			printf("%02d:%02d:%02d %02d:%02d:%02d ",s[now].day,s[now].time/60,s[now].time%60,s[now+1].day,s[now+1].time/60,s[now+1].time%60);
			sum+=cal(s[now].day,s[now+1].day,s[now].time,s[now+1].time);
			now+=2;//两个两个处理
		} 
		printf("Total amount: $%.2lf\n",sum);
	}
	return 0;
	
}

1017 Queueing at Bank (25 分)

题目大意:

银行一共有K个窗口提供服务。每个窗口前有一条黄线,将等候区分成两个部分。所有客户都要站在黄线后排队等候,直到轮到他被叫号。客户在窗口办理业务的时间不能超过1个小时。早上八点前到达的客户需等到银行开门,下午五点之后到达的客户不会被提供服务

银行从早上八点开始营业,下午五点关门。给出客户到达银行的时间和办理业务所需时间,求所有客户的平均等候时间。

思路:

1、使用结构体记录客户到达银行的时间,处理业务所需时间。若出现 17 : 00 17:00 17:00之后到的,直接忽略。

2、按照到达时间从小到大排序,将每个窗口空闲时间初始化为早上八点

3、如果某客户到达时间早于窗口空闲时间,则客户需要等待,否则无需等待。

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> p;
inline ll lowbit(ll x){return x&(-x);}
struct Customer{
	int arrive;
	int time;
	int wait;
}cus[maxn];
struct Windows{
	int endtime;
}win[maxn];
bool cmp(Customer a,Customer b){
	return a.arrive<b.arrive;
}
int main(){
	int n,k;
	cin>>n>>k;
	int cnt=0;
	for(int i=0;i<n;i++){
		int h,m,s,t;
		scanf("%d:%d:%d %d",&h,&m,&s,&t);
		int tt=h*3600+m*60+s;
		if(tt>17*3600) continue;
		cus[cnt].arrive=tt;
		cus[cnt++].time=t*60;
	}
	sort(cus,cus+cnt,cmp);
	for(int i=0;i<k;i++){
		win[i].endtime=8*3600;
	}
	int idx=0;
	while(idx<cnt){
		int d=cus[idx].arrive;
		int pos=0;
		int end=win[0].endtime;
		for(int i=1;i<k;i++){//找最早空闲的窗口
			if(win[i].endtime<end){
				end=win[i].endtime;
				pos=i;
			}
		}
		if(d<=end){
			cus[idx].wait=end-d;
			win[pos].endtime+=cus[idx].time;
		}
		else win[pos].endtime=d+cus[idx].time; 
		idx++;
	}
	double ans=0;
	for(int i=0;i<cnt;i++){
		ans+=cus[i].wait;
	}
	printf("%.1lf\n",ans/60/cnt);
	return 0;
	
}

1018 Public Bike Management (30 分)

题目大意:

PBMC监控整个城市所有自行车停靠点内的实时自行车容量。如果自行车停靠点的容量是最大容量的一半,那么该自行车停靠点达到完美状态。如果某自行车停靠点内的自行车太多或者太少,PBMC将会收回或者发送相应数量的自行车,从而使得该停靠点达到完美状态。

给出一个存在问题的停靠点,求PBMC前往该停靠点的最短路,PBMC同时会将这条路途径的所有停靠点调整到完美状态。如果最短路不止一条,PBMC将会选择需要从PBMC发送最少数量自行车的那条路。

思路:

1、dij求最短路,因为最后要输出最短路,所以每次更新最短路时,需要同步记录路径

2、dfs遍历最短路,同时求走这条最短路,PBMC需要发送和回收的自行车数量

3、选择需要发送自行车数量最少的那条最短路,如果存在多条,则选择需要回收自行车数量最少的那条路

#include<bits/stdc++.h>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
const int maxn=1e4+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> p;
inline ll lowbit(ll x){return x&(-x);}
int cmax,n,s,m,minneed,minback;
int e[maxn][maxn];
int dis[maxn];
int vis[maxn];
int num[maxn];
vector<int>road[maxn],tmp,ans;
void dij(){//求最短路
	memset(dis,INF,sizeof(dis));
	for(int i=0;i<=n;i++){
		dis[i]=e[0][i];
	}
	int num=0;
	for(int i=0;i<=n;i++){
		int mmin=INF,u=-1;
		for(int j=0;j<=n;j++){
			if(!vis[j]&&dis[j]<mmin){
				mmin=dis[j];
				u=j;
			}
		}
		if(u==-1) break;
		vis[u]=1;
		for(int j=0;j<=n;j++){
			if(!vis[j]&&dis[j]>dis[u]+e[u][j]){
				dis[j]=dis[u]+e[u][j];
				road[j].clear();//更新最短路
				road[j].pb(u);
			}
			else if(!vis[j]&&dis[j]==dis[u]+e[u][j]){
				road[j].pb(u);
			}
		}
	}
}
void dfs(int x){//寻找最优的最短路
	tmp.pb(x);
	if(x==0){
		int need=0,back=0;
		for(int i=tmp.size()-2;i>=0;i--){
			int id=tmp[i];
			if(num[id]>cmax){
				back+=num[id]-cmax;
			}
			if(num[id]==cmax) continue;
			if(num[id]<cmax){
				int res=cmax-num[id];
				if(back<res){
					need+=(res-back);
					back=0;
				}
				else back-=res;
			}
		}
		if(need<minneed){
			minneed=need;
			ans=tmp;
			minback=back;
		}
		else if(need==minneed&&back<minback){
			minback=back;
			ans=tmp;
		}
	}
	for(int i=0;i<road[x].size();i++){
		dfs(road[x][i]);
	}
	tmp.pop_back();//回溯
}
int main(){
	cin>>cmax>>n>>s>>m;
	cmax/=2;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=n;j++){
			if(i==j) e[i][j]=0;
			else e[i][j]=INF;
		}
	}
	for(int i=1;i<=n;i++){
		cin>>num[i];
	}
	while(m--){
		int u,v,w;
		cin>>u>>v>>w;
		e[u][v]=e[v][u]=w;
	}
	minneed=INF,minback=INF;
	dij();
	dfs(s);
	cout<<minneed<<" 0";
	for(int i=ans.size()-2;i>=0;i--){
		cout<<"->"<<ans[i];
	}
	cout<<" "<<minback<<endl;
	return 0;
	
}

1019 General Palindromic Number (20 分)

题目大意:

判断十进制数N在b进制下,是否为回文数。

误区:不能用string来处理!!!

进制数b的范围 [ 2 , 1 0 9 ] [2,10^9] [2,109];

string存char字符,最高127,如果超过127自动模128。

所以只能用int数组处理

(我发现,似乎并没有n=0,这个测试点。)

#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int a[maxn];
int main()
{
	int n,b;
	cin>>n>>b;
	int j=0;
	while(n!=0){
		a[j++]=n%b;
		n/=b;
	}
	int flag=1;
	for(int i=0;i<j;i++){
		if(a[i]!=a[j-i-1]){
			flag=0;
		}
	}
	if(!flag) puts("Yes");
	else puts("No");
	for(int i=j-1;i>=0;i--){
		if(i==j-1)
	    cout<<a[i];
	    else cout<<" "<<a[i];
	}
    return 0;
}

1020 Tree Traversals (25 分)

题目大意:

已知二叉树后序和中序遍历,求其层序遍历

#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
map<int,int>level;
int post[maxn],in[maxn];
int n;
void pre(int root,int l,int r,int idx){
	if(l>r) return;
	int k=post[root];
	int i=l;
	while(i<=r&&in[i]!=k) i++;
	level[idx]=k;
	pre(root-r+i-1,l,i-1,2*idx+1);
	pre(root-1,i+1,r,2*idx+2);
}
int main()
{
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>post[i];
	}
	for(int i=0;i<n;i++){
		cin>>in[i];
	}
	pre(n-1,0,n-1,0);
	map<int,int>::iterator it=level.begin();
	cout<<it->second;
	it++;
	for(;it!=level.end();it++){
		cout<<" "<<it->second;
	}
	cout<<endl;
    return 0;
}

1021 Deepest Root (25 分)

题目大意:

给出n个点n-1条边,问是否能构成一棵树,如果不能构成则输出它有的连通分量个数,如果能构成一棵树,输出能构成最深的树的高度时,树的根结点。如果有多个,按照从小到大输出。

1、dfs求连通块个数

2、dfs求树的最大高度

#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
vector<int>e[maxn],ans;
int vis[maxn];
int cnt;
int mmax,h;
void dfs(int x){
	vis[x]=1;
	for(int i=0;i<e[x].size();i++){
		if(!vis[e[x][i]]) dfs(e[x][i]);
	}
}
void high(int x,int num){
	if(num>h){
		h=num;
	}
	vis[x]=1;
	for(int i=0;i<e[x].size();i++){
		if(!vis[e[x][i]]){
			high(e[x][i],num+1);
		}
		
	}
}
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n-1;i++){
		int u,v;
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			dfs(i);
			cnt++;
		}
	}
	if(cnt>1){
		printf("Error: %d components",cnt);
	}
	else{
		for(int i=1;i<=n;i++){
			h=0;
			memset(vis,0,sizeof(vis));
			high(i,0);
			if(h>mmax){
				mmax=h;
				ans.clear();
				ans.push_back(i);
			}
			else if(h==mmax){
				ans.push_back(i);
			}
		}
		sort(ans.begin(),ans.end());
		for(int i=0;i<ans.size();i++){
			cout<<ans[i]<<endl;
		}
	}
    return 0;
}

1022 Digital Library (30 分)

题目大意:

给出书籍信息,查找符合条件的相应书籍编号

考虑到最终结果要求输出书籍编号,且书籍编号唯一,故用map做映射,id为键,其他书籍信息为值。

按照题目要求查找即可。

#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
map<string,string>title,author,key,pub,year;
int main(){
	int n;
	cin>>n;
	getchar();//吸收空格
	while(n--){
		string id,t,a,k,p,y;
		getline(cin,id);
		getline(cin,t);
		getline(cin,a);
		getline(cin,k);
		getline(cin,p);
		getline(cin,y);
		title[id]=t;
		author[id]=a;
		key[id]=k;
		pub[id]=p;
		year[id]=y;
	}
	int m;
	cin>>m;
	while(m--){
		int k;
		scanf("%d: ",&k);
		string s;
		getline(cin,s);
		cout<<k<<": "<<s<<endl;
		map<string,string>::iterator it;
		int flag=0;
		if(k==1){
			for(it=title.begin();it!=title.end();it++){
				string t=it->second;
				if(t==s){
					flag=1;
					cout<<it->first<<endl;
				}
			}
		}
		else if(k==2){
			for(it=author.begin();it!=author.end();it++){
				string t=it->second;
				if(t==s){
					flag=1;
					cout<<it->first<<endl;
				}
			}
		}
		else if(k==3){
			for(it=key.begin();it!=key.end();it++){
				string t=it->second;
				if(t.find(s)!=-1){
					flag=1;
					cout<<it->first<<endl;
				}
			}
		}
		else if(k==4){
			for(it=pub.begin();it!=pub.end();it++){
				string t=it->second;
				if(t==s){
					flag=1;
					cout<<it->first<<endl;
				}
			}
		}
		else if(k==5){
			for(it=year.begin();it!=year.end();it++){
				string t=it->second;
				if(t==s){
					flag=1;
					cout<<it->first<<endl;
				}
			}
		}
		if(!flag) puts("Not Found");
	}
    return 0;
}

1023 Have Fun with Numbers (20 分)

题目大意:

判断将一个数翻倍后,其各位数字组成是否发生变化,并输出计算结果。

模拟加法

#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int num1[10],num2[10];
string cal(string a,string b){
	string ans="";
	int jw=0;
	for(int i=a.length()-1;i>=0;i--){
		int x=a[i]-'0';
		int y=b[i]-'0';
		int t=x+y;
		if(jw){
			t++;
			jw=0;
		}
		if(t>=10){
			t-=10;
			jw=1;
		}
		ans+=to_string(t);
	}
	if(jw) ans+=to_string(jw);
	reverse(ans.begin(),ans.end());
	return ans;
}
int main(){
	string s;
	cin>>s;
	for(int i=0;i<s.length();i++){
		num1[s[i]-'0']++;
	}
	string t=cal(s,s);
	for(int i=0;i<t.length();i++){
		num2[t[i]-'0']++;
	}
	int flag=1;
	for(int i=0;i<10;i++){
		if(num1[i]!=num2[i]){
			flag=0;
			break;
		}
	}
	if(flag) puts("Yes");
	else puts("No");
	cout<<t<<endl;
    return 0;
}

1024 Palindromic Number (25 分)

题目大意:

给出一个数字,将其与自身翻转后的到的数字相加,直到变成一个回文数。输出这个回文数,并输出需要多少步。

模拟加法,回文数判断

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+10;
int check(string a){
	string b=a;
	reverse(a.begin(),a.end());
	if(a==b) return 1;
	else return 0;
}
string add(string a,string b){
	string ans;
	int jw=0;
	for(int i=a.length()-1;i>=0;i--){
		int num=a[i]-'0'+b[i]-'0';
		if(jw){
			num+=jw;
			jw=0;
		}
		if(num>=10){
			num-=10;
			jw=1;
		}
		ans+=num+'0';
	}
	if(jw) ans+=jw+'0';
	reverse(ans.begin(),ans.end());
	return ans;
}
int main()
{
	string s,t;
	int k;
	cin>>s>>k;
	t=s;
	for(int i=1;i<=k;i++){
		reverse(s.begin(),s.end());
		if(s==t){
			cout<<s<<endl;
			cout<<"0\n";
			return 0;
		}
		t=add(s,t);
		s=t;
		if(check(t)){
			cout<<t<<endl;
			cout<<i<<endl;
			return 0;
		}
	}
	cout<<t<<endl;
	cout<<k<<endl;
    return 0;
}

1025 PAT Ranking (25 分)

题目大意:

简单结构体排序

#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct stu{
	string id;
	int g;
	int lrank;
	int rank;
	int num;
}s[maxn];
bool cmp(stu a,stu b){
	if(a.g!=b.g) return a.g>b.g;
	else return a.id<b.id;
}
int main(){
	int n;
	cin>>n;
	int cnt=0;
	int t=0;
	for(int i=1;i<=n;i++){
		int m;
		cin>>m;
		while(m--){
			string id;
			int g;
			cin>>id>>g;
			s[cnt].id=id;
			s[cnt].g=g;
			s[cnt++].num=i;
		}
		sort(s+t,s+cnt,cmp);
		s[t].lrank=1;
		for(int i=t+1;i<cnt;i++){
			if(s[i].g==s[i-1].g){
				s[i].lrank=s[i-1].lrank;
			}
			else s[i].lrank=i-t+1;
		}
		t=cnt;
	}
	sort(s,s+cnt,cmp);
	s[0].rank=1;
	for(int i=1;i<cnt;i++){
		if(s[i].g==s[i-1].g){
			s[i].rank=s[i-1].rank;
		}
		else s[i].rank=i+1;
	}
	cout<<cnt<<endl;
	for(int i=0;i<cnt;i++){
		cout<<s[i].id<<" "<<s[i].rank<<" "<<s[i].num<<" "<<s[i].lrank<<endl;
	}
    return 0;
}

1026 Table Tennis (30 分)

题目大意:

1027 Colors in Mars (20 分)

注意:若输入的是一位数,必须在前面补一个0

input:0 0 0

output:#000000

#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e4;
void change(int b){
	int a[maxn];
	int j=0;
	do{
	  a[j++]=b%13;
	  b/=13;
	}while(b!=0);
	if(j==1)//补0
	cout<<"0"; 
	for(int i=j-1;i>=0;i--){
		if(a[i]==10) cout<<"A";
		else if(a[i]==11) cout<<"B";
		else if(a[i]==12) cout<<"C";
		else cout<<a[i];
	}
}
int main()
{
	int a,b,c;
	cin>>a>>b>>c;
	cout<<"#";
	change(a);change(b);change(c);
    return 0;
}

1028 List Sorting (25 分)

按照题目要求进行相应排序即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct stu{
	string id,name;
	int grade;
}s[maxn];
int n,m;
void print(){
	for(int i=0;i<n;i++){
		cout<<s[i].id<<" "<<s[i].name<<" "<<s[i].grade<<endl;
	}
}
bool cmp1(stu a,stu b){
	return a.id<b.id;
}
bool cmp2(stu a,stu b){
	if(a.name!=b.name)
	return a.name<b.name;
	else return a.id<b.id; 
}
bool cmp3(stu a,stu b){
	if(a.grade!=b.grade)
	return a.grade<b.grade;
	else return a.id<b.id;
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>s[i].id>>s[i].name>>s[i].grade;
	}
	if(m==1) sort(s,s+n,cmp1);
	else if(m==2) sort(s,s+n,cmp2);
	else sort(s,s+n,cmp3);
	print();
    return 0;
}

1029 Median (25 分)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+10;
vector<int>v;
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		int x;
		cin>>x;
		v.push_back(x);
	}
	int m;
	cin>>m;
	for(int i=0;i<m;i++){
		int x;
		cin>>x;
		v.push_back(x); 
	}
	sort(v.begin(),v.end());
	cout<<v[(n+m-1)/2]<<endl;
	
    return 0;
}

1030 Travel Plan (30 分)

#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int n,m,s,d,cnt;
struct edge{
	int u,v,w,c;
	int next;
}e[maxn];
int head[maxn];
int dis[maxn];
int cost[maxn];
int vis[maxn];
vector<int>road[maxn],ans;
void add(int u,int v,int w,int c){
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].c=c;
	e[cnt].next=head[u];
	head[u]=cnt++;
}
void dfs(int x){
	ans.push_back(x);
	if(x==s) return;
	for(int i=0;i<road[x].size();i++){
		dfs(road[x][i]);
	}
}
void dij(){
	memset(dis,INF,sizeof(dis));
	memset(cost,INF,sizeof(cost));
	dis[s]=0;
	cost[s]=0;
	for(int i=0;i<n;i++){
		int mmin=INF,u=-1;
		for(int j=0;j<n;j++){
			if(!vis[j]&&dis[j]<mmin){
				mmin=dis[j];
				u=j;
			}
		}
		if(u==-1) break;
		vis[u]=1;
		for(int j=head[u];j!=-1;j=e[j].next){
			int v=e[j].v;
			if(dis[v]>dis[u]+e[j].w){
				dis[v]=dis[u]+e[j].w;
				cost[v]=cost[u]+e[j].c;
				road[v].clear();
				road[v].push_back(u);
			}
			else if(dis[v]==dis[u]+e[j].w&&cost[v]>cost[u]+e[j].c){
				cost[v]=cost[u]+e[j].c;
				road[v].clear();
				road[v].push_back(u);
			}
		}
	}
	dfs(d);
	for(int i=ans.size()-1;i>=0;i--){
		cout<<ans[i]<<" ";
	}
	cout<<dis[d]<<" "<<cost[d]<<endl;
} 
int main(){
	cin>>n>>m>>s>>d;
	memset(head,-1,sizeof(head));
	while(m--){
		int u,v,w,c;
		cin>>u>>v>>w>>c;
		add(u,v,w,c);
		add(v,u,w,c);
	}
	dij();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值