有n个城市,标号为1到n,修建道路花费m天,第i天时,若gcd(a,b)=m-i+1,则标号为a的城市和标号为b的城市会建好一条直接相连的道路,有多次询问,每次询问某两座城市最早什么时候能连通。
第一行输入三个正整数n,m,q,其中q表示询问个数。
接下来q行,每行两个正整数x,y,表示询问城市x和城市y最早什么时候连通。
输出q行,每行一个正整数,表示最早连通的天数
Input 1
8 3 3
2 5
3 6
4 8
Input 2
25 6 1
20 9
Input 3
9999 2222 2
1025 2405
3154 8949
Output 1
3
1
2
Output 2
4
Output 3
1980
2160
对于40%的数据,n≤ 1000,q<=100000
对于100%的数据,1 ≤ n,q≤ 100000,1<=m<=q
考试时文件输入输出打错了!!!!!!!!!!!!!!!!!!!
这题让我想起一题叫历史。做法差不多。
开一个并查集,枚举时间,用安置合并,记录每个点加入并查集的时间。
求解时二分时间点,判断这两个点是否在同一集合即可
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100077;
int n,m,q,f[maxn],z[maxn],ti[maxn];
int gf(int x,int t)
{while(x!=f[x]&&ti[x]<=t) x=f[x];return x;
}
void init()
{for(int i=1; i<=n; i++) f[i]=i,z[i]=1;for(int i=1; i<=m; i++){int p=m-i+1;int j=2;while(p*j<=n){int x=gf(p,i),y=gf(p*j,i);if(x!=y){if(z[x]<z[y]) {f[x]=y; z[y]+=z[x]; ti[x]=i;}else {f[y]=x; z[x]+=z[y]; ti[y]=i;}}j++; }}
}
int main()
{freopen("pictionary.in","r",stdin); freopen("pictionary.out","w",stdout);scanf("%d%d%d",&n,&m,&q);init();while(q--){int x,y;scanf("%d%d",&x,&y);int l=1,r=m;while(l<=r){int mid=(l+r)>>1,u=gf(x,mid),v=gf(y,mid);if(u==v) r=mid-1;else l=mid+1;}printf("%dn",l);}
}
本文发布于:2024-01-28 17:21:55,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17064337219020.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |