潜入苏拉玛(BFS+构造)

Posted suiyue-li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了潜入苏拉玛(BFS+构造)相关的知识,希望对你有一定的参考价值。

问题 A: 潜入苏拉玛

时间限制: 1 Sec 内存限制: 128 MB

题目描述

你接到了?个任务,让你潜?苏拉玛城,和线?取得联络。苏拉玛的地图是?张N个点M条边的?向图,每个点表?苏拉玛城的?个路?,每条边表?苏拉玛内的?条道路,长度都是1。你从S号节点出发,线?在T号节点。
由于苏拉玛城内都是夜之?的哨兵,你需要假?伪装才能在苏拉玛的道路上??。你的伪装只能坚持你?完K段道路不被发现,幸好在苏拉玛城内还有P个内应(分别在节点ai上),他们可以修复你的伪装,让它恢复到刚开始的状态。
你想知道K?少需要是多少,才能让你成功找到线?。

输入

第???个正整数CAS表?测试数据组数。
每组测试数据第??有三个数N,M,P如上?所述,第??P个数表?内应的位置。接下来M?,每?2个数表??条边。最后??S和T表?你开始的节点和你的?标节点。

输出

对于每组数据:如果你?法到达线?那?,输出-1,否则输出最?的K。

样例输入

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

样例输出

3
-1

提示

对于100%的数据,1≤K,S,T≤N≤100000,1≤M≤150000,1≤CAS≤5。

思路:

把起点、终点、内应都视为原点。
假设答案一定是偶数,也就是从(S)(T)经过两个相邻原点的距离都(le 2K)
这样问题就转化为从每个原点出发(bfs) 各走(k)步,走出的点集是(S,T)联通。
如果(S=T,ans=0)。否则,
每次将相邻的点加入,重新(bfs),相当于(ans+=2)
但是答案显然有奇数的情况,我们只需在每条边中间加一条中间点,也就是说如果(i-j)有一条边,改为(i-x,x-j)个有一条边。这样就保证了结果一定是偶数,最后把答案(div 2)即可。
注意到是无向图,判连通性可以用并查集,加上线性的遍历,最终复杂度就是(O(nlogn))

//#pragma GCC optimize(2)
//#pragma GCC optimize(3, "Ofast", "inline")
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
const int N=1e6+5;
const ll mod=1e9+7;
const double eps=1e-5;
//const double pi=acos(-1);
vector<int>g[N];
int vis[N],f[N];
int getf(int x)
{
    return f[x]==x?x:f[x]=getf(f[x]);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int _;
    cin>>_;
    while(_--)
    {
        int n,m,k;
        cin>>n>>m>>k;
        queue<int>q,p;
        memset(vis,0,sizeof vis);
        for(int i=1;i<=m*2;i++) g[i].clear(),f[i]=i;
        for(int j=0,x;j<k;j++)
        {
            cin>>x;
            if(!vis[x])
                q.push(x),vis[x]=1;
        }
        k=n+1;
        while(m--)
        {
            int u,v;
            cin>>u>>v;
            g[u].push_back(k);
            g[k].push_back(u);
            g[k].push_back(v);
            g[v].push_back(k);
            k++;
        }
        int x,y;
        cin>>x>>y;
        if(!vis[x]) q.push(x),vis[x]=1;
        if(!vis[y]) q.push(y),vis[y]=1;
        int ans=0;
        while(1)
        {
            ans++;
            if(q.empty())
            {
                ans=-1;break;
            }
            while(!q.empty())
            {
                int u=q.front();q.pop();
                for(auto v:g[u])
                {
                    int uu=getf(u),vv=getf(v);
                    if(uu>vv) swap(uu,vv);
                    f[vv]=uu;
                    if(vis[v]) continue;
                    p.push(v);
                    vis[v]=1;
                }
            }
            if(getf(x)==getf(y))
                break;
            while(!p.empty())
            {
                q.push(p.front());p.pop();
            }

        }
        cout<<ans<<‘
‘;

    }
    return 0;
}
































以上是关于潜入苏拉玛(BFS+构造)的主要内容,如果未能解决你的问题,请参考以下文章

HDU3247 Resource Archiver(AC自动机+BFS+DP)

在 Visual Studio 中创建构造函数的代码片段或快捷方式

海蒂·拉玛:被誉为WiFi之母的好莱坞女星

FZOJ P2109 卡德加的兔子

无法解析片段中的 ViewModelProvider 构造?

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段