一个链接:https://ac.nowcoder.com/acm/contest/82/E
来源:牛客网
无向图中的最短距离
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
有一个n个点的无向图,有m次查询,每次查询给出一些(xi,yi)
令dist(x,y)表示x和y点在图中最短距离,dist(x,x)=0,如果x,y不连通则dist(x,y) = inf
每次查询图中有多少个点v与至少一个这次询问给出的(xi,yi)满足dist(v,xi)<=yi
输入描述:
第一行三个数表示n,m,q
之后m行每行两个数x,y表示有一条x与y之间的边,边权为1
之后q次询问,每个询问先给你一个数a
之后一行2a个数,第2i-1个数xi和第2i个数yi表示一个二元组(xi,yi)
输出描述:
输出q行,每行一个数表示这次询问的答案
备注:
对于100%的数据,n <= 1000 , m <= 100000 , q <=
100000
a的和<= 2100000
题意:
给你一个有向图,然后q个询问,每一个询问给你num个对数x,y 。
问你在图中有多少个节点与这num对个数中的至少一对中的x的距离小于等于y。
思路:
首先对于每一个节点进行bfs找到它对其他节点的最短路。
用数组 dis[i][j] 来维护 i到j的距离,
那么我们定理一个 bitset<1011> bs[1011][1011]
bs[i][j][k] 代表 第i个节点距离小于等于j的有没有k,有没有只有两个状态,即0/1
所以用 bitset可以完美维护。
对于处理,
我们对每一个节点bfs后,更新 bs
repd(j,1,n)
{
bs[i][dis[i][j]][j]=1;
}
又因为是 小于等于, 所以 bs[i][j][k] =1的话, 那么bs[i][j~n][k] 都为1.
这样我们就可以从1到n,用bitset 的或运算|=来更新使距离j更大的一定包含更小的情况。
然后对于询问,
我们只需要让一个全是0的bitset 去|= 那num个 bs[x][y] 即可。
最后得到的bitset中的1的个数就是答案数。
细节见代码:
#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d ",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), ' ', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;} inline void getInt(int* p); const int maxn = 1010; const int inf = 0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ int n; int dis[maxn][maxn]; bitset<maxn> bs[maxn][maxn]; int m; int q; bitset<maxn> res; std::vector<int> G[maxn]; void bfs(int x) { dis[x][x] = 0; queue<int> q; q.push(x); while (!q.empty()) { int u = q.front(); q.pop(); for (auto y : G[u]) { if (~dis[x][y])continue; dis[x][y] = dis[x][u] + 1; q.push(y); } } } int main() { // freopen("D:\common_text\code_stream\in.txt","r",stdin); // freopen("D:\common_text\code_stream\out.txt","w",stdout); memset(dis, -1, sizeof(dis)); gbtb; cin >> n >> m >> q; int x, y; repd(t, 1, m) { cin >> x >> y; G[x].push_back(y); G[y].push_back(x); } repd(i, 1, n) { bfs(i); repd(j, 1, n) { bs[i][dis[i][j]][j] = 1; } repd(j, 1, n) { bs[i][j] |= bs[i][j - 1]; } } int num; repd(t, 1, q) { cin >> num; res.reset(); repd(i, 1, num) { cin >> x >> y; res |= bs[x][y]; } cout << res.count() << endl; } return 0; } inline void getInt(int* p) { char ch; do { ch = getchar(); } while (ch == ' ' || ch == ' '); if (ch == '-') { *p = -(getchar() - '0'); while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 - ch + '0'; } } else { *p = ch - '0'; while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 + ch - '0'; } } }