HDU 5876 补图最短路

开两个集合,一个存储当前顶点可以到达的点,另一个存储当前顶点不能到达的点。如果可以到达,那肯定由该顶点到达是最短的,如果不能,那就留着下一次再判。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn=200000+5;

int T;
int n, m, s;
int d[maxn];
vector<int> G[maxn];

void bfs()
{
    queue<int> Q;
    Q.push(s);
    set<int> t1,t2;
    set<int>::iterator it;
    for(int i=1;i<=n;i++)  if(i!=s)  t1.insert(i);
    while(!Q.empty())
    {
        int u=Q.front(); Q.pop();
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            if(!t1.count(v))  continue;
            t1.erase(v);  //删去u点不能到达的点
            t2.insert(v);  //将这些点放入t2中供下一次使用
        }
        for(it=t1.begin();it!=t1.end();it++)  //这些点都是u能到达的
        {
            d[*it]=d[u]+1;  
            Q.push(*it);
        }
        t1.swap(t2);  //t2中存储的是还没到达过的点
        t2.clear();
    }
    bool flag=true;
    for(int i=1;i<=n;i++)
    {
        if(i==s)  continue;
        if(!flag)  printf(" ");
        if(flag)   flag=false;
        if(d[i]==-1)  printf("-1");
        else printf("%d",d[i]);
    }
    printf("\n");
}

int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)  G[i].clear();
        while(m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        scanf("%d",&s);
        memset(d,-1,sizeof(d));
        d[s]=0;
        bfs();
    }
    return 0;
}

 

posted @ 2019-08-06 19:22  Aragaki  阅读(153)  评论(0编辑  收藏  举报