Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。
Z小镇附近共有
N(1<N≤500)个景点(编号为1,2,3,…,N),这些景点被M(0<M≤5000)条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。频繁的改变速度使得游客们很不舒服,因此大家从一个景点前往另一个景点的时候,都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。
第一行包含两个正整数,N和M。
接下来的M行每行包含三个正整数:x,y和v(1≤x,y≤N,0 最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
样例1
4 2
1 2 1
3 4 2
1 4
样例2
3 3
1 2 10
1 2 5
2 3 8
1 3
样例3
3 2
1 2 2
2 3 4
1 3
样例1
IMPOSSIBLE
样例2
5/4
样例3
2
N(1<N≤500)
M(0<M≤5000)
Vi在int范围内
事实上 标准算法并查集,把边按边权排序,然后一条条添加进去,一旦起始点和结束点连通,那么当前连法就是需要找的最优方案,此时输出就好,如果所有边都查询过了还是不能连通,就输出“IMPOSSIBLE”
帖代码
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,hs[100007];
bool pd[100007];
int hash(int x)
{
int t=x%100007;
while(pd[t]&&hs[t]!=x)
t=(t+1)%100007;
pd[t]=1;
return t;
}
int main(){
memset(pd,0,sizeof(pd));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
hs[hash(t)]=t;
}
for(int i=1;i<=m;i++)
{
int t;
scanf("%d",&t);
if(hs[hash(t)]==t) printf("YES\n");
else printf("NO\n");
}
return 0;
}
(QAQ代码似乎略凌乱。。。算了你们自己分析去吧www)
2.CODEVS2842可怜的帆帆
水题
和舒适的路线一样解法
帆帆很可爱,但RP太差。
他费尽千辛万苦逃出了迷宫,却又掉进了一座超大的迷宫。
这次,可怜的帆帆没有地图,但他在地上发现了一张发黄的纸,上面写着M行数字。
数字代表哪两个亭子间有路径,长度为多少。
帆帆在s号亭子,出口是t号亭子。(共有N个)
但帆帆太小,身体不够强壮,两亭子间走的路太长就会不舒服。
如果最长与最短路径相差太大,他也会不舒服。
求帆帆怎样最舒服地走出迷宫?
N,M
起点 终点 长度(M行)
s t
若没有路径,输出IMPOSSIBLE。
否则输出最小的最长和最短单条路径的比。需要输出最简分数或整数。
3 3
1 2 10
1 2 5
2 3 8
1 3
8/5
N《=500,M《=5000。
s不等于t。
3.CODEVS3372选学霸
老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议。所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近。
第一行,三个正整数N,M,K。
第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1…N)。
一行,表示既不让同学们抗议,又与原来的M尽可能接近的选出学霸的数目。(如果有两种方案与M的差的绝对值相等,选较小的一种。)
4 3 2
1 2
3 4
2
100%的数据N,P<=30000
算法:并查集+背包,并查集找完个数之后背包DP一下就好了,找一种与m的差值最小的方案就是答案
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,hs[100007];
bool pd[100007];
int hash(int x)
{
int t=x%100007;
while(pd[t]&&hs[t]!=x)
t=(t+1)%100007;
pd[t]=1;
return t;
}
int main(){
memset(pd,0,sizeof(pd));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
hs[hash(t)]=t;
}
for(int i=1;i<=m;i++)
{
int t;
scanf("%d",&t);
if(hs[hash(t)]==t) printf("YES\n");
else printf("NO\n");
}
return 0;
}
感谢Rivendile(ZYH)大神提供的代码援助! @赵怡浩
4.CODEVS2751军训分批
某学校即将开展军训。共有N个班级。
前M个优秀班级为了保持学习优势,必须和3位任课老师带的班级同一批。
问共有几批?
N,M
老师教的其他班级(M行)
批次数
4 2
1 1 1
2 3 1
2
对于50%数据,N,M<=1000.
对于100%数据,N,M<=30000,N<=M.
水题,合并完集合找一找总共几个集合就行了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;int f[30001];
int num;
int find(int x)
{
if (f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
void union_set(int a,int b)
{
int t1,t2;
t1=find(a);
t2=find(b);
if (t1!=t2)
f[t2]=t1;
}
main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
f[i]=i;
for (int i=1;i<=m;i++)
for (int j=1;j<=3;j++)
{
int a; scanf("%d",&a);
union_set(i,a);
}
for (int i=1;i<=n;i++)
if (f[i]==i) num++;
cout<<num;
}