7-2 列出连通集 (25 分)

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

思路:先dfs,再bfs即可,但是注意在bfs之前要把vis数组再一次的初始化。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=;
int n,m;
int a,b;
int ma[maxn][maxn];
bool vis[maxn];
vector<int>ans;
void dfs(int x)
{
if(vis[x])
return ;
vis[x]=true;
ans.push_back(x);
for(int i=;i<n;i++)
{
if(ma[x][i])
dfs(i);
}
}
void bfs(int x)
{
if(vis[x])
return;
queue<int>q;
q.push(x);
ans.push_back(x);
vis[x]=true;
while(!q.empty())
{
int tem=q.front();
q.pop();
for(int i=;i<n;i++)
{
if(ma[tem][i] && !vis[i])
{
q.push(i);
ans.push_back(i);
vis[i]=true;
}
}
}
}
int main()
{
cin>>n>>m;
memset(vis,false,sizeof(vis));
memset(ma,,sizeof(ma));
while(m--)
{
cin>>a>>b;
ma[a][b]=ma[b][a]=;
}
for(int i=;i<n;i++)
{
ans.clear();
dfs(i);
int len=ans.size();
if(len!=)
{
cout<<"{ ";
for(int j=;j<len;j++)
cout<<ans[j]<<" ";
cout<<"}"<<endl;
}
}
memset(vis,false,sizeof(vis));
for(int i=;i<n;i++)
{
ans.clear();
bfs(i);
int len=ans.size();
if(len!=)
{
cout<<"{ ";
for(int j=;j<len;j++)
cout<<ans[j]<<" ";
cout<<"}"<<endl;
}
}
return ;
}
7-3 排序 (25 分)

给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。

本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:

  • 数据1:只有1个元素;
  • 数据2:11个不相同的整数,测试基本正确性;
  • 数据3:103个随机整数;
  • 数据4:104个随机整数;
  • 数据5:105个随机整数;
  • 数据6:105个顺序整数;
  • 数据7:105个逆序整数;
  • 数据8:105个基本有序的整数;
  • 数据9:105个随机正整数,每个数字不超过1000。

输入样例:

11
4 981 10 -17 0 -20 29 50 8 43 -5

输出样例:

-20 -17 -5 0 4 8 10 29 43 50 981
思路;可以选择一些nlogn 的排序算法去写,但是这题也可以水过去。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std; bool cmp(const int &a,const int &b){
if(a < b)
return true;
return false;
}
int main()
{
int i,j,N,num;
vector<int> s;
vector<int>::iterator it;
cin>>N;
for(i=;i<N;i++){
cin>>num;
s.push_back(num);
}
sort(s.begin(),s.end(),cmp);
for(it=s.begin();it!=s.end();it++){
if(it!=s.begin())
cout<<" ";
cout<<(*it);
}
return ;
}
7-4 QQ帐户的申请与登陆 (25 分)

实现QQ新帐户申请和老帐户登陆的简化版功能。最大挑战是:据说现在的QQ号码已经有10位数了。

输入样例:

5
L 1234567890 myQQ@qq.com
N 1234567890 myQQ@qq.com
N 1234567890 myQQ@qq.com
L 1234567890 myQQ@qq
L 1234567890 myQQ@qq.com

输出样例:

ERROR: Not Exist
New: OK
ERROR: Exist
ERROR: Wrong PW
Login: OK

思路:用map存储,然后到对应的情况就在map里面查询即可,不同的情况对应着不同的答案。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int maxn=;
int n;
int a[maxn];
char c;
map<string,string>ma;
string s1,s2;
int main()
{
cin>>n;
for(int i=;i<=n;i++)
{
cin>>c;
if(c=='L')
{
cin>>s1>>s2;
if(ma.count(s1)==)
cout<<"ERROR: Not Exist"<<endl;
else if(ma[s1]==s2)
cout<<"Login: OK"<<endl;
else
cout<<"ERROR: Wrong PW"<<endl;
}
else
{
cin>>s1>>s2;
if(ma.count(s1)==)
{
cout<<"New: OK"<<endl;
ma[s1]=s2;
}
else
cout<<"ERROR: Exist"<<endl;
}
}
return ;
}
7-5 求前缀表达式的值 (25 分)

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。

输入样例:

+ + 2 * 3 - 7 4 / 8 4

输出样例:

13.0
思路:了解前缀表达式的求值,先把字符串读入进来,然后从后往前,将读取出来的值放到stack 容器里面,如果读到操作符,就取出栈顶的两个元素进行运算,将运算的结果再存储到栈中。注意除数不能为0,以及最后的时候栈不能有数值了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=;
int n;
string s;
stack<double>ss;
bool flag=;
int main()
{
getline(cin,s);
int len=s.length();
double sum=;
int t=;
for(int i=len-;i>=;i--)
{
if(s[i]>=''&&s[i]<='')
{
sum+=(s[i]-'')*t;
t*=;
}
else if(s[i]=='.')
{
sum=sum/(t*1.0);
t=;
}
else if((s[i]=='+'||s[i]=='-')&&sum!=)
{
if(s[i]=='+')
{
ss.push(sum);
i--;
continue;
}
else
{
ss.push(-sum);
i--;
continue;
}
}
else if(s[i]==' ')
{
ss.push(sum);
sum=;t=;
continue;
}
else if(s[i]=='+' || s[i]=='-' || s[i]=='*' || s[i]=='/')
{
double a = ss.top();
ss.pop();
double b = ss.top();
ss.pop();
double tt = ;
if(s[i] == '+')
tt = a+b;
else if(s[i] == '-')
tt = a-b;
else if(s[i] == '*')
tt = a*b;
else if(s[i] == '/')
{
if(b == )
{
flag = ;
break;
}
tt = a/b;
}
ss.push(tt);
i--;
}
}
if(flag != )
printf("%.1lf\n",ss.top());
else
printf("ERROR\n");
return ;
}
7-8 集合相似度 (25 分)

给定两个整数集合,它们的相似度定义为:/。其中N​c​​是两个集合都有的不相等整数的个数,N​t​​是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。

输入样例:

3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3

输出样例:

50.00%
33.33%

思路:题意就是找到两个集合相同数值的数的个数,就可以用set 存储一个集合里面的元素,然后用一个set 里面的元素去匹配另一个set,得到相同数值的数的个数就可以了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
const int maxn=;
int n,m,k,t;
int a,b;
set<int>s[maxn];
int main()
{
cin>>n;
for(int i=;i<=n;i++)
{
cin>>m;
while(m--)
{
cin>>k;
s[i].insert(k);
}
}
cin>>m;
while(m--)
{
cin>>a>>b;
int sa=s[a].size();
int sb=s[b].size();
int same=;
set<int>::iterator it;
for(it=s[a].begin();it!=s[a].end();it++)
{
if(s[b].find(*it)!=s[b].end())
same++;
}
double ans=same*1.0*/(sa+sb-same);
printf("%.2f%%\n",ans);
}
return ;
}
7-9 图着色问题 (25 分)

图着色问题是一个著名的NP完全问题。给定无向图G=(V,E),问可否用K种颜色为V中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色?

但本题并不是要你解决这个着色问题,而是对给定的一种颜色分配,请你判断这是否是图着色问题的一个解。

输入样例:

6 8 3
2 1
1 3
4 6
2 5
2 4
5 4
5 6
3 6
4
1 2 3 3 1 2
4 5 6 6 4 5
1 2 3 4 5 6
2 3 4 2 3 4

输出样例:

Yes
Yes
No
No

思路:用二维数组ma[][]存储边,然后按给的颜色去查,如果边相同,且颜色相同就不满足题意。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn=;
int n,m,k,q;
int ma[maxn][maxn];
int col[maxn];
set<int>s;
int main()
{
scanf("%d %d %d",&n,&m,&k);
memset(ma,,sizeof(ma));
while(m--)
{
int a,b;
scanf("%d %d",&a,&b);
ma[a][b]=ma[b][a]=;
}
scanf("%d",&q);
while(q--)
{
bool flag=false;
for(int i=;i<=n;i++)
{
scanf("%d",&col[i]);
s.insert(col[i]);
}
if(s.size()!=k)
flag=true;
else
{
for(int i=;i<=n&&!flag;i++)
{
for(int j=i+;j<=n&&!flag;j++)
{
if(ma[i][j])
{
if(col[i]==col[j])
flag=true;
}
}
}
}
if(flag)
printf("No\n");
else
printf("Yes\n");
s.clear();
}
return ;
}
7-10 出栈序列的合法性 (25 分)

给定一个最大容量为 M 的堆栈,将 N 个数字按 1, 2, 3, ..., N 的顺序入栈,允许按任何顺序出栈,则哪些数字序列是不可能得到的?例如给定 M=5、N=7,则我们有可能得到{ 1, 2, 3, 4, 5, 6, 7 },但不可能得到{ 3, 2, 1, 7, 5, 6, 4 }。

输入样例:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

输出样例:

YES
NO
NO
YES
NO

思路:就是走一遍存储的过程,用stack 去模拟出栈的情况,如果能够模拟成功就是YES,否则就是NO。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=;
stack<int>s;
queue<int>q;
int a[maxn];
int main()
{
int m,n,k;
cin>>m>>n>>k;
while(k--)
{
stack<int>s;
for(int i=;i<n;i++)
{
cin>>a[i];
}
int i=,j=;
while(s.size()<m && j<n)
{
s.push(i);//按开始的顺序push
i++;
while(!s.empty()&&j<n&&a[j]==s.top())//看给定的出栈顺序,相同则pop
{
j++;
s.pop();
}
if(i==n+)
break;
}
if(i==n+ && s.empty())
printf("YES\n");
else
printf("NO\n");
}
return ;
}
7-11 文件传输 (25 分)

当两台计算机双向连通的时候,文件是可以在两台机器间传输的。给定一套计算机网络,请你判断任意两台指定的计算机之间能否传输文件?

输入样例 1:

5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S

输出样例 1:

no
no
yes
There are 2 components.
思路:并查集的简单应用,开始没看清题意,只有到最后的时候才需要判断联通集,并不需要在全联通的时候输出
The network is connected.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=;
int n;
int fa[maxn];
int cnt[maxn];
char c;
int a,b;
void init()
{
for(int i=;i<=n;i++)
{
fa[i]=i;
cnt[i]=;
}
}
int findd(int x)
{
if(fa[x]==x)
return fa[x];
else
return fa[x]=findd(fa[x]);
}
void join(int x,int y)
{
int fx=findd(x),fy=findd(y);
if(fx!=fy)
{
fa[fx]=fy;
cnt[fy]+=cnt[fx];
cnt[fx]=;
}
}
int main()
{
cin>>n;
init();
while(cin>>c)
{
if(c=='S')
{
int sum=;
for(int i=;i<=n;i++)
{
if(cnt[i])
sum++;
}
if(sum==)
printf("The network is connected.");
else
printf("There are %d components.\n",sum);
break;
}
else if(c=='C')
{
cin>>a>>b;
if(findd(a)!=findd(b))
cout<<"no"<<endl;
else
cout<<"yes"<<endl;
}
else
{
cin>>a>>b;
join(a,b);
}
}
return ;
}
7-12 汉密尔顿回路 (25 分)

著名的“汉密尔顿(Hamilton)回路问题”是要找一个能遍历图中所有顶点的简单回路(即每个顶点只访问 1 次)。本题就要求你判断任一给定的回路是否汉密尔顿回路。

输入样例:

6 10
6 2
3 4
1 5
2 5
3 1
4 1
1 6
6 3
1 2
4 5
6
7 5 1 4 3 6 2 5
6 5 1 4 3 6 2
9 6 2 1 6 3 4 5 2 6
4 1 2 5 1
7 6 1 3 4 5 2 6
7 6 1 2 5 4 3 1

输出样例:

YES
NO
NO
NO
YES
NO
思路:用二维数组ma[][]存边,然后按给的答案顺序判断,当点没访问过并且存在边的时候符合题意,否则就是NO
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=;
int n,m,k;
int a,b;
int ma[maxn][maxn];
bool vis[maxn];
int aa[maxn];
int main()
{
memset(ma,,sizeof(ma));
cin>>n>>m;
for(int i=;i<=n;i++)
ma[i][i]=;
while(m--)
{
cin>>a>>b;
ma[a][b]=ma[b][a]=;
}
cin>>m;
while(m--)
{
memset(vis,false,sizeof(vis));
cin>>k;
for(int i=;i<=k;i++)
cin>>aa[i];
if(k!=n+)
cout<<"NO"<<endl;
else if(aa[]!=aa[k])
cout<<"NO"<<endl;
else
{
int flag=;
vis[aa[]]=true;
for(int i=;i<k;i++)
{
if(vis[aa[i]] || !ma[aa[i-]][aa[i]])
{
flag=;
break;
}
vis[aa[i]]=true;
}
if(!ma[aa[k-]][aa[k]])
flag=;
if(flag)
printf("YES\n");
else
printf("NO\n");
}
}
return ;
}
7-14 与零交换 (25 分)

将 { 0, 1, 2, ..., N-1 } 的任意一个排列进行排序并不困难,这里加一点难度,要求你只能通过一系列的 Swap(0, *) —— 即将一个数字与 0 交换 —— 的操作,将初始序列增序排列。例如对于初始序列 { 4, 0, 2, 1, 3 },我们可以通过下列操作完成排序:

  • Swap(0, 1) ⟹ { 4, 1, 2, 0, 3 }
  • Swap(0, 3) ⟹ { 4, 1, 2, 3, 0 }
  • Swap(0, 4) ⟹ { 0, 1, 2, 3, 4 }

本题要求你找出将前 N 个非负整数的给定排列进行增序排序所需要的最少的与 0 交换的次数。

输入样例:

10
3 5 7 2 6 4 9 0 8 1

输出样例:

9
思路:找循环节。(3,0,7,2),(5,1,9,6,4),(8)三个
第一个节(包含0)需要循环节长度-1次操作,即可把其它元素移到对应的位置
第二个节(不包含0)需要循环节长度+1次操作,可以看成向循环节中加入0(操作次数加1),
那么循环节长度加1(交换时次数要加1),总共比包含0的情况多操作两次
第三个节是一个元素,那么不需要任何操作。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn=;
int n;
int a[maxn],b[maxn];
int vis[maxn];
map<int,int>ma;
void dfs(int x,int t)
{
if(vis[x])
return ;
vis[x]=t;
dfs(b[x],t);
}
int main()
{
memset(vis,,sizeof(vis));
cin>>n;
for(int i=;i<n;i++)
{
cin>>a[i];
b[a[i]]=i;
}
int cnt=;
for(int i=;i<n;i++)
{
if(!vis[i])
{
dfs(a[i],cnt);
cnt++;
}
}
for(int i=;i<n;i++)
ma[vis[i]]++;
int ans=;
for(int i=;i<cnt;i++)
{
if(ma[i]==)
continue;
if(i==vis[])
ans+=ma[i]-;
else
ans+=ma[i]+;
}
printf("%d\n",ans);
return ;
}

2019天梯赛练习题(L2专项练习)的更多相关文章

  1. 2019天梯赛练习题(L1专项练习)

    7-1 水仙花数 (20 分) 水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身.例如:1. 本题要求编写程序,计算所有N位水仙花数. 输入样例: 3 输出样例: 153 ...

  2. PAT天梯赛练习题——L3-007. 天梯地图(多边权SPFA)

    L3-007. 天梯地图 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 本题要求你实现一个天梯赛专属在线地图,队员输入自己学校 ...

  3. PAT天梯赛练习题 L3-002. 堆栈(线段树查询第K大值或主席树)

    L3-002. 堆栈 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家都知道“堆栈”是一种“先进后出”的线性结构,基本操作有 ...

  4. PAT天梯赛练习题 L3-010. 是否完全二叉搜索树(完全二叉树的判断)

    L3-010. 是否完全二叉搜索树 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 将一系列给定数字顺序插入一个初始为空的二叉搜 ...

  5. PAT天梯赛练习题 L3-011. 直捣黄龙(多关键字SPFA+DFS)

    L3-011. 直捣黄龙 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 本题是一部战争大片 —— 你需要从己方大本营出发,一路 ...

  6. PAT天梯赛练习题 L2-013 红色警报(并查集+逆序加边)

    L2-013. 红色警报 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 战争中保持各个城市间的连通性非常重要.本题要求你编写一 ...

  7. 天梯赛练习题L2-006. 树的遍历

    题目链接 已知一棵树的后序遍历顺序和中序遍历顺序,求层次遍历的顺序: 树的四种遍历: 先序遍历:先访问根节点,再访问左子树,最后访问右子树 中序遍历:先访问左子树,再访问根节点,最后访问右子树 后序遍 ...

  8. PAT天梯赛练习题——L3-004. 肿瘤诊断(三维连通块并查集)

    L3-004. 肿瘤诊断 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环.给定病灶 ...

  9. PAT天梯赛练习题——L3-005. 垃圾箱分布(暴力SPFA)

    L3-005. 垃圾箱分布 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁 ...

随机推荐

  1. githunb竟然可以识别MQ4

    完全是上班时候突发奇想,没想到能识别.只是没有现成的gitignore

  2. BZOJ3834:Solar Panels (分块)

    题意 询问两个区间[smin,smax],[wmin,smax]中是否存在k的倍数,使得k最大 分析 将其转化成\([\frac{smin-1}k,\frac{smax}k],[\frac{wmin- ...

  3. C#读取大文件

    有些时候需要读取文件,小文件的时候效率的影响可以忽略,但是当文件上M,上G的时候,这个时候,效率问题就非常重要了,下面将对一个3G的文件,用C#的方式读取,对比效率的影响. 1. FileStream ...

  4. ES6之箭头函数深入理解

    相对于普通函数的区别 新的书写方式 this 的改变 不能当构造函数 没有 prototype 属性 没有 arguments 对象 新的书写方式 书写方式很简单!直接看下图, 常规方式写一个函数 c ...

  5. Database UVA - 1592

    对于每组数据,首先通过一个map将每个字符串由一个数字代替,相同的字符串由相同数字代替,不同的字符串由不同数字代替.那么题目就变为了询问是否存在行r1,r2以及列c1,c2使得str[r1][c1]= ...

  6. adb shell getprop,setprop,watchprops更改,查看,监听系统属性

    1.简介 每个属性都有一个名称和值,他们都是字符串格式.属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换.属性是在整个系统中全局可见的.每个进程可以get/set属性.  在 ...

  7. 520 Detect Capital 检测大写字母

    给定一个单词,你需要判断单词的大写使用是否正确.我们定义,在以下情况时,单词的大写用法是正确的:    全部字母都是大写,比如"USA".    单词中所有字母都不是大写,比如&q ...

  8. subline应用之技巧

    看很多人代码编辑器都用subline,一了解这货也跨平台.支持代码提示自动补全.支持python.语法高亮.最关键的是支持列编辑(原来以为只有ue有此功能),那就果断下载使用,挺好! 列编辑:首先用鼠 ...

  9. C#结构体和类的区别(转)

    结构体和类的区别:    在做一个项目时,使用了较多的结构体,并且存在一些结构体的嵌套,即某结构体成员集合包含另一个结构体等,总是出现一些奇怪的错误,才终于下决心好好分析一下到底类和结构体有啥不同,虽 ...

  10. AJPFX总结I/O流操作(一)

    在软件开发中,数据流和数据库操作占据了一个很重要的位置,所以,熟悉操作数据流和数据库,对于每一个开发者来说都是很重要的,今天就来总结一下I/O,数据库操作 一:从数据流开始 首先先有一个结构图看一下整 ...