2017省夏令营Day8
题解:出题人丧心病狂~ 对于这道题,我们对每一个内应节点bfs,并用并查集维护,如果s和t联通,输出答案并break。
PS几个小细节:①对于每个内应dis=0,为了保证不会对答案产生影响,我们在每2个节点中插入一个新的节点即可;
②因为加入新节点,数组要开大些,否则会炸。
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define Max 2020304 5 using namespace std; 6 int n,m,k,s,t,dis[Max],fa[Max],hd,tl,q[Max*2]; 7 int tot,to[Max],next[Max],head[Max]; 8 bool flag,vis[Max]; 9 void add(int x,int y){ 10 to[++tot]=y; next[tot]=head[x]; head[x]=tot; 11 to[++tot]=x; next[tot]=head[y]; head[y]=tot; 12 } 13 int find(int x){ 14 if(fa[x]==0) return x; 15 return fa[x]=find(fa[x]); 16 } 17 void prework(){ 18 flag=true; hd=0; tl=k; 19 memset(fa,0,sizeof(fa)); 20 memset(vis,0,sizeof(vis)); 21 memset(dis,-1,sizeof(-1)); 22 for(int i=1;i<=k;i++) vis[q[i]]=true,dis[q[i]]=0; 23 } 24 void bfs(){ 25 prework(); 26 while(hd<tl){ 27 int vex=q[++hd]; if(!flag) break; 28 for(int i=head[vex];i;i=next[i]){ 29 if(!flag) break; 30 int u=find(vex),v=find(to[i]); 31 if(u!=v) fa[u]=v; 32 if(find(s)==find(t)){printf("%d\n",dis[vex]+1); flag=false; break;} 33 if(!vis[to[i]]){ 34 dis[to[i]]=dis[vex]+1; 35 vis[q[++tl]=to[i]]=true; 36 } 37 } 38 } 39 if(flag) printf("-1\n"); 40 } 41 int main() 42 { 43 freopen("masquerade.in","r",stdin); 44 freopen("masquerade.out","w",stdout); 45 int T; scanf("%d",&T); 46 while(T--){ 47 memset(head,tot=0,sizeof(head)); 48 memset(to,0,sizeof(to)); 49 memset(next,0,sizeof(next)); 50 scanf("%d%d%d",&n,&m,&k); 51 for(int i=1;i<=k;i++) scanf("%d",&q[i]); 52 int now=n; 53 for(int i=1;i<=m;i++){ 54 int x,y; scanf("%d%d",&x,&y); 55 add(x,++now); add(now,y); 56 } 57 scanf("%d%d",&s,&t); q[++k]=t; 58 bfs(); 59 } 60 }
---------------------------------------------------------------华丽的分割线------------------------------------------------------------------------
---------------------------------------------------------------华丽的分割线------------------------------------------------------------------------