zoukankan      html  css  js  c++  java
  • 潜入苏拉玛(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;
    }
    
  • 相关阅读:
    一致性哈希算法
    Discourse 的标签(Tag)只能是小写的原因
    JIRA 链接 bitbucket 提示错误 Invalid OAuth credentials
    JIRA 如何连接到云平台的 bitbucket
    Apache Druid 能够支持即席查询
    如何在 Discourse 中配置使用 GitHub 登录和创建用户
    Apache Druid 是什么
    Xshell 如何导入 PuTTYgen 生成的 key
    windows下配置Nginx支持php
    laravel连接数据库提示mysql_connect() :Connection refused...
  • 原文地址:https://www.cnblogs.com/Suiyue-Li/p/12838132.html
Copyright © 2011-2022 走看看