题意:给一个图 给定一个点s 求补图中s点到达各个点的最短路
思路:从s点开始bfs 在图中与s点有连接的都是在补图中不能直接到达的点 反之在补图中都是可以直接到达的点 由此bfs ((( 诡异的写法。。。
AC代码:
#include "iostream"
#include "string.h"
#include "stack"
#include "queue"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
#define max(a,b) a > b ? a : b
#define min(a,b) a < b ? a : b
#define INF 20005
using namespace std; int dis[];
int vis[]; vector<int>Node[]; void Delete_Edge(int u,int v)
{
Node[u].push_back(v);
Node[v].push_back(u);
} void fun(int s,int n)
{
queue<int>Q;
set<int> s1;
set<int> s2;
set<int> *ss;
set<int> *ss1 = &s1;
set<int> *ss2 = &s2;
Q.push(s);
dis[s] = ;
vis[s] = ;
for(int i=; i<=n; i++)
s1.insert(i);
s1.erase(s); while(!Q.empty())
{
int r=Q.front();
Q.pop();
for(int i=; i<Node[r].size(); i++)
{
if(!ss1->count(Node[r].at(i))) continue;
ss2->insert(Node[r].at(i)); //未找到
ss1->erase(Node[r].at(i)); //找到
}
set<int>::iterator it;
for(it=ss1->begin(); it!=ss1->end(); it++)
{
if(!vis[*it])
{
vis[*it] = ;
dis[*it] = dis[r]+;
Q.push(*it);
}
}
ss1->clear();
ss = ss1, ss1 = ss2, ss2 = ss;
}
} int main()
{
int n,m,t,s;
scanf("%d",&t);
while(t--)
{ mem(vis);
scanf("%d%d",&n,&m);
for(int i = ; i <= n; ++i) dis[i] = ;
for(int i = ; i <= n; ++i) Node[i].clear();
for(int i=; i<=m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
Delete_Edge(u,v);
}
scanf("%d",&s);
fun(s,n);
int k = ;
for(int i=; i<=n; i++)
{
if(i!=s)
{
if(k==)
printf("%d",dis[i]==?-:dis[i]);
else
printf(" %d",dis[i]==?-:dis[i]);
k++;
}
}
printf("\n");
}
return ;
}