HDU 5876 Sparse Graph (补图BFS+(链表||set))

来源:互联网 发布:程序员健康问题 编辑:程序博客网 时间:2024/06/05 05:52

传送门:HDU 5876 Sparse Graph

描述:

Sparse Graph

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 311    Accepted Submission(s): 105


Problem Description
In graph theory, the complement of a graph G is a graph H on the same vertices such that two distinct vertices of H are adjacent if and only if they are notadjacent in G

Now you are given an undirected graph G of N nodes and M bidirectional edges of unit length. Consider the complement of G, i.e., H. For a given vertex S on H, you are required to compute the shortest distances from S to all N1 other vertices.
 

Input
There are multiple test cases. The first line of input is an integer T(1T<35) denoting the number of test cases. For each test case, the first line contains two integers N(2N200000) and M(0M20000). The following M lines each contains two distinct integers u,v(1u,vN) denoting an edge. And S (1SN) is given on the last line.
 

Output
For each of T test cases, print a single line consisting of N1 space separated integers, denoting shortest distances of the remaining N1 vertices from S (if a vertex cannot be reached from S, output ``-1" (without quotes) instead) in ascending order of vertex number.
 

Sample Input
12 01
 

Sample Output
1
 

Source
2016 ACM/ICPC Asia Regional Dalian Online
 

Recommend
wange2014


题意:

求补图的其他的所有点到指定点的最短距离

思路:

补图上的 BFS 是非常经典的问题。一般的做法是用链表(或者偷懒用 std::set)维护还没 BFS 过的点。当要扩展点 u 的时候,遍历一次还没访问过的点 v,如果 uv 没边,那么将 v 入队。否则将 v 留在未扩展点中。

很明显,后者只会发生 m 次,前者只会发生 n 次,所以复杂度是 O(n + m)O(n+m).

PS:16年大连区域赛网赛第七题,原题为SCU4444
代码:

#include<bits/stdc++.h>#define pl(x) cout << #x << "= " << x << endl;using  namespace std;typedef long long ll;const int inf=1e9+7;const int maxn=200100;int n,m;ll d[maxn];bool inq[maxn];set<int>st,ts;int head[maxn],ip;typedef pair<ll,int>P;void init(){  memset(head,-1,sizeof(head));  memset(inq, false, sizeof (inq));  ip=0;}struct note{  int v,w,next;}edge[maxn<<1];void addedge(int u,int v,int w){    edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++;}void Dij(){  priority_queue<P, vector<P>, greater<P> > q;//取最小值  for(int i=1; i<=n; i++)d[i]=inf;  memset(inq, 0, sizeof(inq));  d[1]=0;  q.push(make_pair(0, 1));   while(!q.empty()){    int u,v,w;    P x=q.top();    q.pop();    u=x.second;inq[u]=true;    for(int i=head[u]; i!=-1; i=edge[i].next){      v=edge[i].v;      w=edge[i].w;      if(d[u]+w<d[v]){        d[v]=d[u]+w;        pl(d[v]);        q.push(make_pair(d[v], v));      }    }  }}void bfs(int s){  int i,u,v;  st.clear(); ts.clear();  for(i=1;i<=n;i++){    if(i==s)continue;    st.insert(i);//把数放入集合中  }  queue<int>q;  q.push(s);  d[s]=0,d[n]=inf;  while(!q.empty()){    u=q.front();    q.pop();    for(i=head[u];i!=-1;i=edge[i].next){      v=edge[i].v;      if(st.count(v)==0)continue;//判断当前的数 是否在集合中      st.erase(v);//从当前集合中移除      ts.insert(v);    }    for(set<int>::iterator it=st.begin();it!=st.end();it++){      q.push(*it);      d[*it]=d[u]+1;    }    st.swap(ts); //把两集合内的元素互换    ts.clear();  //当前集合内的元素删去  }}int  main(){  int t,s;  scanf("%d",&t);  while(t--){    scanf("%d%d",&n,&m);    int u,v;    init();    for(int i=1; i<=m ;i++){      scanf("%d%d",&u,&v);      addedge(u, v, inf);      addedge(v, u, inf);    }    scanf("%d",&s);    Dij();    bfs(s);    bool flag=false;    for(int i=1; i<=n; i++){      if(i==s)continue;      if(flag)printf(" ");      if(d[i]==inf)printf("-1");      else printf("%d",d[i]);      flag=true;    }    printf("\n");  }  return 0;}




0 0
原创粉丝点击