HDU

来源:互联网 发布:网游编程课程 编辑:程序博客网 时间:2024/06/03 19:38

题意 : 就是给你一个图求他补图的最短路是多少。

思路: 首先他的点很多,但是边很少,我们不可能根据这个图去构建他的补图,因为点有20w不管怎样都不合适,

那我们就要换一个思路了,就是我们用两个set,第一个set维护一个当前点不能到达的所有点,第二个set表示的是当前点可以到达的所有点,那么我们每次看,如果当前点可以到达的点在第一个set里面我们就吧这个点抹去,把他加入到第二个set里面(点v在第一个set里面出现过就表明当前点u可以到达v,那么就把v抹去,放到第二个set里面),那么放在第一个set里的点肯定都是补图中的和当前边构成的边,那么我们让他+1 就好了,讲的不是很清楚,看代码吧

#include <stdio.h>#include <string.h>#include <iostream>#include <set>#include <queue>#define inf 0x7f7f7fusing namespace std;const int maxn = 200010;struct node{int nex,to;}edg[maxn * 4];int  cnt = 0 ,head[maxn],dist[maxn],n,m;set<int>aa;set<int>bb;  //aa 可以从起点到达的点,bb不能到达的点 queue<int>que;void init(){aa.clear(),bb.clear();for(int i = 0 ; i < maxn ; i++){dist[i] = inf;}memset(head,-1,sizeof(head));}void add(int u,int v){edg[cnt].to = v;edg[cnt].nex = head[u];head[u] = cnt++;}void bfs(int s){while(!que.empty()) que.pop();set<int>::iterator it; for(int i = 0 ; i < n;i++){if(i!=s)aa.insert(i);}dist[s] = 0;que.push(s);while(!que.empty()){int u = que.front();que.pop();for(int i = head[u] ; i !=-1 ;i = edg[i].nex){int v = edg[i].to;if(!aa.count(v)) continue;aa.erase(v);bb.insert(v);}for(it = aa.begin();it!=aa.end();it++){que.push(*it);dist[*it] = dist[u] +1;}aa.swap(bb);bb.clear();}}int main(){int t;scanf("%d",&t);while(t--){cnt = 0 ;init();//printf("%d\n",inf);//puts("----");/*for(int i = 0 ; i < 10;i++){printf("%d\n",dist[i]);}*/scanf("%d%d",&n,&m);int a,b;for(int i = 0 ; i < m ;i++){//cout<<" i ="<<i<<endl;scanf("%d%d",&a,&b);a--,b--;add(a,b);add(b,a);}int s;scanf("%d",&s);bfs(s-1);int ok = 0;for(int i = 0 ; i < n ;i++){if(i != s-1){if( ok == 1 ){printf(" ");}if(dist[i] == inf){printf("-1");}else {printf("%d",dist[i]);}ok = 1; }}puts("");}}