2018TYUT暑期ACM模拟赛(5)
​​​Sparse Graph HDU - 5876​​​
题意:给图G的点数和边集,求图G的补集的一点到其余个点的距离。
思路:因为边的代价都是1所以只要bfs过一遍标记一下就好,只不过边数目太多所以要考虑这个。用set得到所给图的补集的边。边的存储最好还是用邻接表的方式。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<set>
using namespace std;
const int MAXN=200000+10;//点数
const int MAXM=200000+10;//邻接表边数
#include<set>
bool vis[MAXN];
int first[MAXN];
int tt;//初始化为-1
int dis[MAXN];
int n;

struct Edge
{
int to,next;
}edge1[MAXM]; //邻接表 //初始化为0
void add(int a,int b) //添加边
{
edge1[tt].to=b;
edge1[tt].next=first[a];
first[a]=tt++;
}
void bfs(int u)
{
memset(dis,-1,sizeof(dis));
memset(vis,0,sizeof(vis));
set<int> st,ts;
queue<int> q;
for(int i=1;i<=n;i++)
if(i!=u) st.insert(i);
q.push(u);
dis[u]=0;
vis[u]=1;
while(!q.empty())
{
int v=q.front();//cout<<"v "<<v<<endl;
q.pop();
for(int i=first[v];~i;i=edge1[i].next)
{
int tmp=edge1[i].to;
st.erase(tmp),ts.insert(tmp);
}
for(set<int>::iterator it=st.begin();it!=st.end();it++)
{
if(!vis[*it])
{
vis[*it]=1;
dis[*it]=dis[v]+1; // cout<<"dis "<<dis[*it]<<endl;
q.push(*it);
}
}
st.swap(ts);
ts.clear();
}
for(int i=1;i<=n;i++)
{
if(i!=u)
{
printf("%d",dis[i]);
if(i!=n) printf(" ");
}

}
}
int main()
{
int t;
int m;
int u,v,s;
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
memset(first,-1,sizeof(first));tt=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
if(u!=v)
{
add(u,v);//存边
add(v,u);
}
}
scanf("%d",&s);
bfs(s);
printf("\n");
}

}
return 0;
}