preparing

网络流24题 - 3

题目顺序按照洛谷“\(\color{#13C2C2}{网络流24题}\)”标签按难度排序。
题目的字体颜色为洛谷此题难度的颜色。
本人的题单: 网络流24题

P4015 \(\color{#9D3DCF}{运输问题}\)

题目大意

\(n\)间商店和\(m\)间仓库。仓库分别有\(a_1,a_2,…,a_m\)的存货,商店分别需要\(b_1,b_2,…,b_n\)的货物,满足总存货量等于总需求量,即\(\sum\limits_{i=1}^{m}{a_i}=\sum\limits_{j=1}^{n}{b_j}\)。从仓库\(i\)\(1\)个单位的货到商店\(j\)需花费\(c_{i,j}\)的费用,求把存货全部运至商店且均满足需货量的最小费用与最大费用。

思路

有了前\(8\)题的经验,这题一看就是要跑最小&最大费用最大流。我们建超级源点\(s\)和超级汇点\(t\)\(s\)连向所有的仓库且对于仓库\(i\)\(f=a_i,c=0\),即提供\(a_i\)的流量,代表存货(因为是存货所以显然是免费的);所有的商店连向\(t\)且对于商店\(i\)\(f=b_i,c=0\),即这个商店要被提供且最多被提供\(b_i\)的货量(实际上只能有\(b_i\),因为如果这里少了,其他地方也不能多,故少不了);对于仓库\(i\)与商店\(j\)之间,连接\(f=\infty,c=c_{i,j}\)的边,因为可以不限量(在存货范围内)供货且收费\(c_{i,j}\)。剩下的就是跑板子了,要跑两遍,和上次的\(P4014\)很像。

细节

  • 没啥细节,板子别错就行

代码

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 5005
#define maxm 50005
#define ll long long
#define inf 0x3fffffff
using namespace std;
ll n,m,x,s,t,cost;
ll ina[maxn],inb[maxn],inc[maxn][maxn];
ll head[maxn],tt=1;
struct node{
	ll to,dis,cost,nex;
}a[maxm*2];
void add(ll from,ll to,ll dis,ll cost){
	a[++tt].to=to;a[tt].dis=dis;a[tt].cost=cost;a[tt].nex=head[from];head[from]=tt;
	a[++tt].to=from;a[tt].dis=0;a[tt].cost=-cost;a[tt].nex=head[to];head[to]=tt;
}
bool vis[maxn];
ll costs[maxn];
bool spfa(){
	memset(vis,0,sizeof(vis));
	memset(costs,0x3f,sizeof(costs));
	queue<int> q;
	vis[s]=1;
	q.push(s);
	costs[s]=0;
	while(!q.empty()){
		ll top=q.front();
		q.pop();
		vis[top]=0;
		for(ll i=head[top];i;i=a[i].nex){
			if(costs[top]+a[i].cost<costs[a[i].to]&&a[i].dis){
				costs[a[i].to]=costs[top]+a[i].cost;
				if(!vis[a[i].to]){
					vis[a[i].to]=1;
					q.push(a[i].to);
				}
			}
		}
	}
	if(costs[t]==costs[0]){
		return 0;
	}
	return 1;
}
ll ans=0,anscost=0;
ll dfs(ll x,ll minn){
	if(x==t){
		vis[t]=1;
		ans+=minn;
		return minn;
	}
	ll use=0;
	vis[x]=1;
	for(ll i=head[x];i;i=a[i].nex){
		if((!vis[a[i].to]||a[i].to==t)&&costs[a[i].to]==costs[x]+a[i].cost&&a[i].dis){
			ll search=dfs(a[i].to,min(minn-use,a[i].dis));
			if(search>0){
				use+=search;
				anscost+=(a[i].cost*search);
				a[i].dis-=search;
				a[i^1].dis+=search;
				if(use==minn){
					break;
				}
			}
		}
	}
	return use;
}
void dinic(int flag){
	while(spfa()){
		do{
			memset(vis,0,sizeof(vis));
			dfs(s,inf);
		}while(vis[t]);
	}
	printf("%lld\n",anscost*flag);
}
void set(){
	memset(head,0,sizeof(head));
	memset(a,0,sizeof(a));
	tt=1;
	ans=anscost=0;
}
int main(){
	scanf("%lld%lld",&m,&n);
	s=n+m+1;
	t=s+1;
	for(int i=1;i<=m;i++){
		scanf("%lld",&ina[i]);
		add(s,i,ina[i],0);
	}
	for(int i=1;i<=n;i++){
		scanf("%lld",&inb[i]);
		add(i+m,t,inb[i],0);
	}
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			scanf("%lld",&inc[i][j]);
			add(i,j+m,inf,inc[i][j]);
		}
	}
	dinic(1);
	set();
	for(int i=1;i<=m;i++){
		add(s,i,ina[i],0);
	}
	for(int i=1;i<=n;i++){
		add(i+m,t,inb[i],0);
	}
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			add(i,j+m,inf,-inc[i][j]);
		}
	}
	dinic(-1);
	return 0;
}

P2770 \(\color{#9D3DCF}{航空路线问题}\)

题目大意

\(\color{red}{自西至东}\)给出一些城市[1],并给出它们之间的航线(无向,图中有线连接代表有航线)。

现要从\(\color{red}{最西边的城市}\)出发,严格\(\color{red}{自西向东}\)沿航线游玩某些城市,最后到达\(\color{red}{最东边的城市}\)。再从\(\color{red}{最东边的城市}\)出发,严格\(\color{red}{自东向西}\)沿航线游玩若干城市,最后回到\(\color{red}{最西边的城市}\),且两条路线上\(\color{red}{不能有重复的城市}\)(除两端点)。求最多能游玩到的城市数,无解输出\(“No\ Solution!”\)。如图答案为\(7\),路线为(反过来也行):$$Vancouver\rightarrow Edmonton\rightarrow Montreal\rightarrow Halifax\rightarrow Toronto\rightarrow Winnipeg\rightarrow Calgary\rightarrow Vancouver$$

思路

注意到题目里的几个关键词,既然“两条路线上不能有重复的城市”,那么我们不妨把题目看作是要找两条互不相交的从\(s\)\(t\)的路径。又因为“每个城市只能经过一次”,但是,;网络流中并没有“点权”这种东西,那么我们可以把一个点拆成两个,一个是“入点”,一个是“出点”,两点之间连\(f=1,c=1\)的边,这样就限制了每条边最多流过一次,也就是某城市最多只经过一次。至于费用等于\(1\),是因为我们最后用费用表示经过了多少城市,即经过一个城市就要付\(1\)的费用。对于点\(i\),我们不妨设点\(i\)为其“入点”,\(i+n\)为其“出点”。把点\(1\),即最西边的城市看做源点\(s\),把点\(n\),即最东边的城市作为汇点\(t\)。对于\(s\)\(t\),入点和出点的流量为\(2\),因为要找两条路。对于有航线的两城市\(i,j\)(假设\(i\)\(j\)西边),则应该把\(i+n\)\(j\)连边,即把\(i\)的出点与\(j\)的入点相连,\(f=1,c=0\),因为只能有\(1\)的流量,而没有经过城市,故\(c=0\)
最后,跑完最大费用最大流后,我们会得到结果。若最大流为\(2\),则说明有至少两条路可以从\(s\)\(t\),则\(DFS\)\(f\)被清零的路线输出即可。若小于\(2\)则无解。但是,若源点直接和汇点相连,此时是有一条路(\(s\rightarrow t\rightarrow s\))满足条件的,应该要特判。

细节

  • 要拆点
  • 字符串开始可以用\(map\)映射成数
  • 要跑最大费用最大流,除了我没人会打成最小费用还调了半小时吧\(\color{rgb(231,76,60)}{WA}\ \ On\ \ Test4\)

代码

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#define maxn 500005
#define maxm 5000005
#define ll long long
#define inf 0x3fffffff
using namespace std;
ll n,m,s,t;
string x,y;
map<string,ll> mp;//城市映射到数
map<ll,string> mp2;//记录数对应的城市
bool flag=0;
ll head[maxn],tt=1;
struct node{
	ll to,dis,cost,nex;
}a[maxm*2];
void add(ll from,ll to,ll dis,ll cost){//正向边反向边一起建
	a[++tt].to=to;a[tt].dis=dis;a[tt].cost=cost;a[tt].nex=head[from];head[from]=tt;
	a[++tt].to=from;a[tt].dis=0;a[tt].cost=-cost;a[tt].nex=head[to];head[to]=tt;
}
bool vis[maxn];
ll costs[maxn];
bool spfa(){
	memset(vis,0,sizeof(vis));
	memset(costs,0x3f,sizeof(costs));
	queue<int> q;
	vis[s]=1;
	q.push(s);
	costs[s]=0;
	while(!q.empty()){
		ll top=q.front();
		q.pop();
		vis[top]=0;
		for(ll i=head[top];i;i=a[i].nex){
			if(costs[top]+a[i].cost<costs[a[i].to]&&a[i].dis){
				costs[a[i].to]=costs[top]+a[i].cost;
				if(!vis[a[i].to]){
					vis[a[i].to]=1;
					q.push(a[i].to);
				}
			}
		}
	}
	if(costs[t]==costs[0]){
		return 0;
	}
	return 1;
}
ll ans=0,anscost=0;
ll dfs(ll x,ll minn){
	if(x==t){
		vis[t]=1;
		ans+=minn;
		return minn;
	}
	ll use=0;
	vis[x]=1;
	for(ll i=head[x];i;i=a[i].nex){
		if((!vis[a[i].to]||a[i].to==t)&&costs[a[i].to]==costs[x]+a[i].cost&&a[i].dis){
			ll search=dfs(a[i].to,min(minn-use,a[i].dis));
			if(search>0){
				use+=search;
				anscost+=(a[i].cost*search);
				a[i].dis-=search;
				a[i^1].dis+=search;
				if(use==minn){
					break;
				}
			}
		}
	}
	return use;
}
void dinic(){
	while(spfa()){
		do{
			memset(vis,0,sizeof(vis));
			dfs(s,inf);
		}while(vis[t]);
	}
	anscost*=-1;
}
ll ansvis[maxn];
void dfs1(ll x){//输出第一条路
	cout<<mp2[x-n]<<endl;//因为是正序输出,故先输出,记得减n
	ansvis[x]=1;//记录搜过的点,防止下次再搜
	for(ll i=head[x];i;i=a[i].nex){//寻找与之相连的边
		if(a[i].to<=n&&!a[i].dis){
			dfs1(a[i].to+n);
			break;
		}
	}
}
void dfs2(ll x){//输出第二条路(从最东边回来)
	for(ll i=head[x];i;i=a[i].nex){//寻找与之相连的边
		if(a[i].to<=n&&!a[i].dis&&!ansvis[a[i].to+n]){//还要判断第一次是否没搜过
			dfs2(a[i].to+n);
		}
	}
	cout<<mp2[x-n]<<endl;//因为是倒序输出,故后输出
}
int main(){
	scanf("%lld%lld",&n,&m);
	s=1;
	t=2*n;//源/汇点
	add(1,1+n,2,-1);//源/汇点的连边要特殊处理,因为流量为2
	add(n,2*n,2,-1);
	for(ll i=1;i<=n;i++){
		cin>>x;
		mp[x]=i;//映射
		mp2[i]=x;
		if(i==1||i==n){
			continue;
		}
		add(i,i+n,1,-1);//入点和出点连边
	}
	for(ll i=1;i<=m;i++){
		cin>>x>>y;
		if(min(mp[x],mp[y])==1&&max(mp[x],mp[y])==n){//起点和终点有直达的边
			flag=1;
		}
		add(min(mp[x],mp[y])+n,max(mp[x],mp[y]),1,0);//防止数据给的顺序是东连向西,故加上min和max
	}
	dinic();//板子
	if(ans==2){//有两条路
		printf("%lld\n",anscost-2);//最大城市数(减2是因为起点和终点算了两次)
		dfs1(1+n);
		dfs2(1+n);
	}else if(ans==1&&flag){//只有起点直达终点的一条路
		printf("2\n");
		cout<<mp2[1]<<endl<<mp2[n]<<endl<<mp2[1];
	}else{//只有一条路或根本没有路则无解
		printf("No Solution!");
	}
	return 0;
}

P2754 \(\color{#9D3DCF}{[CTSC1999]家园 / 星际转移问题}\)

题目大意

\(2177\)年,由于资源破环严重,所有人们被迫移民月球。
现有\(k\)人要从地球前往月球,在地球与月球间有\(n\)个能容纳\(\infty\)人的太空站,有\(m\)艘飞船往返在若干个太空站之间。具体地,第\(i\)艘飞船最多容纳\(h_i\)人,往返于\(r_i\)个太空站\(s_1,s_2,…,s_{r_i}\)之间,如若有一飞船往返于第\(1,3,4\)个太空站之间,那么它将周期性地停靠太空站\(1\;3\;4\;1\;3\;4\;1\;3\;4…\)。特殊地,地球为\(0\),月球为\(-1\)。飞船在两太空站之间消耗的时间均为\(1\),求所有人都到月球上的最短时间(人可以在任意太空站停留任意时间),无解输出\(0\)

思路

首先考虑无解的判断。显然,若不管如何乘坐飞船都无法从地球到月球则无解。那么,我们很容易能想到使用并查集维护能互相到达的太空站/地球/月球,这样就能判断是否有解。
在确定有解的情况下,考虑如何找到最小时间。因为飞船每天停靠的位置不一样,所以这是一幅动态图,考虑在动态图上跑网络流。最难的就是建图部分,考虑到每一天飞船的停靠点不同,我们按照时间把每天的地球\(\&\)月球\(\&\)空间站全部建一个点,如图,每一天(时间的单位不一定是天,为方便以下都用天代替)建\(4\)个节点(地球\(1\)\(+\)月球\(1\)\(+\)本数据中太空站\(2\)个),因为地球和太空站可以留任意时间的任意人数,故上一天的地球\(\&\)太空站都向这天的连一条\(f=\infty\)的边,又由于初始的月球连接着汇点,所以每天的月球向上一天的月球连\(f=\infty\)的边,对于每个太空船\(i\),上一天所在的位置向当天所在位置连一条\(f=h_i\)的边,因为只能容纳\(h_i\)人。此时,每一天跑一边最大流,得到结果\(people_i\)就是这一天能增加运往月球的人数(因为前几天跑最大流的时候把有些边的\(f\)设为\(0\)了,故后面的天数都不会向这些边跑),答案就是最小的\(day\)使得\(\sum\limits_{i=1}^{day}{people_i}\ge k\)

细节

  • 因为不知道有多少天,而且每一天要新建节点,故可以把\(s\)\(t\)的编号设为\(maxn-1\)\(maxn-2\)。此时更新时要循环到\(s\)而不是\(t\),因为\(t\)的下标比\(s\)小。(\(\color{rgb(231,76,60)}{WA}\ \ On\ \ Test1\)
  • 初始要设\(n+2\)个点表示初始状况,也为了第一天的时候能把边连过来。
  • 每天有\(n+2\)个节点,其中地球为第\(1\)个 ,第\(i\)个空间站为第\(i+1\)个,月球为\(n+2\)个,故连边时注意是\((day-1)*(n+2)+1\)是当天的地球,空间站和月球同理(根据代码可变)。
  • 上一天飞船\(i\)的位置是\(orb_{i,((day-1)\mod r_i)}\)\(orb\)记录飞船的运动周期,\(1\)为地球,第\(i\)个空间站为\(i+1\),月球\(n+2\))。

代码

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 20005
#define maxm 500005
#define ll long long
#define inf 0x3fffffff
using namespace std;
int n,m,k,s,t;
ll totpeo=0;//当前天数能最大运到月球的人数
int h[maxn],r[maxn],orb[maxn][maxn];
int head[maxn],tt=1;
int f[maxn];
int find(int x){//并查集-查询
	if(f[x]==x){
		return x;
	}
	return f[x]=find(f[x]);
}
void unionn(int u,int v){//并查集-合并
	int r1=find(u),r2=find(v);
	if(r1!=r2){
		f[r2]=r1;
	}
	return;
}
struct node{
	int to,dis,nex;
}a[maxm*2];
void add(int from,int to,int dis){//正&反向边
	a[++tt].to=to;a[tt].dis=dis;a[tt].nex=head[from];head[from]=tt;
	a[++tt].to=from;a[tt].dis=0;a[tt].nex=head[to];head[to]=tt;
}
bool vis[maxn];
int dep[maxn],cur[maxn];
bool bfs(){
	for(int i=0;i<=s;i++){//更新到s,因为我的代码中t比s的下标小
		vis[i]=0;
		dep[i]=inf;
		cur[i]=head[i];
	}
	queue<int> q;
	vis[s]=1;
	q.push(s);
	dep[s]=0;
	while(!q.empty()){
		int top=q.front();
		q.pop();
		for(int i=head[top];i;i=a[i].nex){
			if(dep[top]+1<dep[a[i].to]&&a[i].dis){
				dep[a[i].to]=dep[top]+1;
				if(!vis[a[i].to]){
					vis[a[i].to]=1;
					q.push(a[i].to);
				}
			}
		}
	}
	return dep[t]!=dep[0];
}
ll ans=0;
int dfs(int x,int minn){
	if(x==t){
		ans+=minn;
		return minn;
	}
	int use=0;
	for(int i=cur[x];i;i=a[i].nex){
		cur[x]=i;
		if(dep[a[i].to]==dep[x]+1&&a[i].dis){
			int search=dfs(a[i].to,min(minn-use,a[i].dis));
			if(search>0){
				use+=search;
				a[i].dis-=search;
				a[i^1].dis+=search;
				if(use==minn){
					break;
				}
			}
		}
	}
	return use;
}
ll dinic(){
	ans=0;
	while(bfs()){
		dfs(s,inf);
	}
	return ans;
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	s=maxn-2;
	t=maxn-3;
	for(int i=1;i<=t;i++) f[i]=i;//并查集
	for(int i=1;i<=m;i++){
		scanf("%d%d",&h[i],&r[i]);
		for(int j=0;j<r[i];j++){//因为mod r[i]的结果为0~r[i]-1,所以下标从0开始
			scanf("%d",&orb[i][j]);
			orb[i][j]++;
			if(orb[i][j]==0) orb[i][j]=n+2;//月球编号为n+2
			if(j!=0) unionn(orb[i][j],orb[i][j-1]);//并查集-合并
		}
	}
	if(find(1)!=find(n+2)){//无法到达
		printf("0");
		return 0;
	}
	add(s,1,inf);
	add(n+2,t,inf);//源点&汇点连到初始的地球&月球
	for(int day=1;;day++){
		for(int i=1;i<=n+1;i++){
			add((day-1)*(n+2)+i,day*(n+2)+i,inf);//地球/空间站的上一天向当天连边
		}
		add(day*(n+2)+n+2,(day-1)*(n+2)+n+2,inf);//月球的当天向上一天连边
		for(int i=1;i<=m;i++){
			int x=(day-1+r[i])%r[i],y=day%r[i];
			add((day-1)*(n+2)+orb[i][x],day*(n+2)+orb[i][y],h[i]);
                        //飞船的当天所在位置向上一天所在位置连边
		}
		totpeo+=dinic();
		if(totpeo>=k){//能运送的最大人数超过总人数即输出答案
			printf("%d",day);
			break;
		}
	}
	return 0;
}

P2762 \(\color{#9D3DCF}{太空飞行计划问题}\)

题目大意

\(m\)项实验和\(n\)种仪器,每项实验需要用到\(n\)种仪器其中的若干种。完成某项实验\(i\)会得到\(p_i\)美元,购置某种仪器\(i\)需花费\(c_i\)美元,求能得到的最大利润。

思路

建超级源点\(s\)和超级汇点\(t\)\(s\)向每一项实验\(i\)连权值为\(p_i\)的边;每一种仪器\(i\)\(t\)连权值为\(c_i\)的边;每项实验向其所需仪器连权值为\(\infty\)的边。我们让\(s\)与实验\(i\)之间的边割掉表示要做此实验,仪器向\(t\)的边割掉表示要选此仪器,此时跑最小割得到结果(因为最小割后图中没有从\(s\)\(t\)的路径,所以选实验\(i\)后,其需要的仪器到\(t\)的边一定会被割掉)。
现在证明结论正确性:令选的实验的下标集合为\(P\),选的仪器的下标集合为\(C\),那么:
\(ans=\max(\sum\limits_{i\in P}{p_i}-\sum\limits_{i\in C}{c_i})=\sum\limits_{i=1}^{m}{p_i}-\min(\sum\limits_{1\le i\le m且i\notin P}{p_i}+\sum\limits_{i\in C}{c_i})=\sum\limits_{i=1}^{m}{p_i}-最小割\)
其实就是:
\(ans=\max(\)要选的实验的收益和\(-\)要选的仪器的花费和\()=\)全部的实验收益\(-min(\)不选的实验收益和\(+\)要选的仪器的花费和\()=\)全部的试验收益\(-\)最小割。(因为不选的实验和要选的仪器我们将他们割掉了)

细节

  • 此题的读入特殊,除了用题中给的读入,还可以用以下改进的快读(题解中找到的):
点击查看代码
inline int read(){
    char c;int r=0;
    while (c<'0' || c>'9') c=getchar();
    while (c>='0' && c<='9')
    {
        r=r*10+c-'0';
        c=getchar();
    }
    if (c=='\n') flag=1;
    return r;
}

代码

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 205
#define maxm 5005
#define ll long long
#define inf 0x3fffffff
using namespace std;
bool flag=0;
inline int read(){
    char c;int r=0;
    while (c<'0' || c>'9') c=getchar();
    while (c>='0' && c<='9')
    {
        r=r*10+c-'0';
        c=getchar();
    }
    if (c=='\n') flag=1;
    return r;
}
int n,m,s,t,fy,xx,totf;
int head[maxn],tt=1;
struct node{
	int to,dis,nex;
}a[maxm*2];
void add(int from,int to,int dis){
	a[++tt].to=to;a[tt].dis=dis;a[tt].nex=head[from];head[from]=tt;
	a[++tt].to=from;a[tt].dis=0;a[tt].nex=head[to];head[to]=tt;
}
bool vis[maxn];
int dep[maxn],cur[maxn];
bool bfs(){
	for(int i=0;i<=t;i++){
		vis[i]=0;
		dep[i]=inf;
		cur[i]=head[i];
	}
	queue<int> q;
	vis[s]=1;
	q.push(s);
	dep[s]=0;
	while(!q.empty()){
		int top=q.front();
		q.pop();
		for(int i=head[top];i;i=a[i].nex){
			if(dep[top]+1<dep[a[i].to]&&a[i].dis){
				dep[a[i].to]=dep[top]+1;
				if(!vis[a[i].to]){
					vis[a[i].to]=1;
					q.push(a[i].to);
				}
			}
		}
	}
	return dep[t]!=dep[0];
}
ll ans=0;
int dfs(int x,int minn){
	if(x==t){
		ans+=minn;
		return minn;
	}
	int use=0;
	for(int i=cur[x];i;i=a[i].nex){
		cur[x]=i;
		if(dep[a[i].to]==dep[x]+1&&a[i].dis){
			int search=dfs(a[i].to,min(minn-use,a[i].dis));
			if(search>0){
				use+=search;
				a[i].dis-=search;
				a[i^1].dis+=search;
				if(use==minn){
					break;
				}
			}
		}
	}
	return use;
}
void dinic(){
	while(bfs()){
		dfs(s,inf);
	}
}
void output(){
	for(int i=head[s];i;i=a[i].nex){
		if(dep[a[i].to]!=inf){
			printf("%d ",a[i].to);
		}
	}
	printf("\n");
	for(int i=head[t];i;i=a[i].nex){
		if(dep[a[i].to]!=inf){
			printf("%d ",a[i].to-m);
		}
	}
	printf("\n%d",totf-ans);
}
int main(){
	scanf("%d%d",&m,&n);
	s=n+m+1;
	t=s+1;
	for(int i=1;i<=m;i++){
		scanf("%d",&fy);
		totf+=fy;
		add(s,i,fy);
		flag=0;
		while(!flag){
			xx=read();
			add(i,m+xx,inf);
		}
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&xx);
		add(m+i,t,xx);
	}
	dinic();
	output();
	return 0;
}
/*
2 2
10 1
20 2
20 10
*/

\(To\ be\ continued…\)


  1. 自西向东的城市的翻译依次为:
    \(Vancouvar\)温哥华
    \(Yellowknife\)耶洛奈夫
    \(Edmonton\)埃德蒙顿
    \(Calgary\)卡尔加里
    \(Winnipeg\)温尼伯
    \(Toronto\)多伦多
    \(Montreal\)蒙特利尔
    \(Halifax\)哈利法克斯 ↩︎

posted @ 2021-08-26 19:58  qzhwlzy  阅读(54)  评论(0)    收藏  举报