문제가 해결, 이해를 많이하지 않습니다에서이 제한되어
이 곤약을 시청 해 주셔서 감사
주제 :
교실 조명 개선 된 버전의 여덟
시간 제한 : 1 초 메모리 제한 : 128 MB의제출 : 79 해결 : 38
[ 제출 ] [ 상태 ] [ 웹 보드 ]
기술
M N 개의 연결 VIII 양방향 경로 교실 (1 <= N, M < = 3000). 전체 팔을 종료하기 위해, 마스터 총리는 모든이 종료 할 계획
교실에서 마감했다. 교실이 꺼진 경우, 도로의 교실에 연결된 모든 폐쇄되고, 더 이상 사용할 수 없습니다. 마스터
원자바오 알고 지금 관심이 그 때마다 그의 팔에 ( "시간"각 전에 시간을 의미 교실을 폐쇄) 할 때 "모든 - 인
소통은"- 하나부터 열 것을 교실은 다른 하나의 교실에 도달하기 시작했다. 일정 시간 이후 그 주, 수도
전체 팔이되지 않습니다 시작 "완전히 연결."
교실에서 마감했다. 교실이 꺼진 경우, 도로의 교실에 연결된 모든 폐쇄되고, 더 이상 사용할 수 없습니다. 마스터
원자바오 알고 지금 관심이 그 때마다 그의 팔에 ( "시간"각 전에 시간을 의미 교실을 폐쇄) 할 때 "모든 - 인
소통은"- 하나부터 열 것을 교실은 다른 하나의 교실에 도달하기 시작했다. 일정 시간 이후 그 주, 수도
전체 팔이되지 않습니다 시작 "완전히 연결."
입력
첫 번째 라인은 수 N, M, N 대표 강의실, M은 가장자리 제공 1 <= N, M < = 200,000
사이에 연결된 경우 교실 설명하는 N 라인 뒤에
다음 N 열, 각 행을 교실 조명을 폐쇄하는 나타내는 숫자
사이에 연결된 경우 교실 설명하는 N 라인 뒤에
다음 N 열, 각 행을 교실 조명을 폐쇄하는 나타내는 숫자
산출
N 출력 라인, 각각의 출력은 "YES"또는 "NO".
전체 통신의 시작에서 출력의 첫 줄이없는 여덟이면
뒤에 N-1 램프의 종류를 설명하기 위해 사용되는 폐쇄 후, 여덟 연통 아니다 가.
전체 통신의 시작에서 출력의 첫 줄이없는 여덟이면
뒤에 N-1 램프의 종류를 설명하기 위해 사용되는 폐쇄 후, 여덟 연통 아니다 가.
샘플 입력
4 3
1 2
2 3
3 4
3
4
1
2
샘플 출력
YES
NO
YES
YES
힌트
효과에 따라 :
, 삭제 요청 점은, 이제 모든 필드 포인트 당신은 m과 n 포인트가 삭제 된 점 (점 영구적으로 사라 삭제 될)마다 가장자리, 또한 삭제이 시점 가장자리에 연결되어 이 통신 할 수 있는지 여부.
주제 분석 :
如果要边输入边删点的话,那么肯定要构造一棵树,并且还要找删点后一个还未删的点去进行搜索,看整个图是否连通,如果数据小还好,但如果数据大的话,肯定会超时。
那么我们换一种思路,既然是看整个图是否连通,那么是不是看每一个的根结点是否一致,那么最好的方法就是使用并查集,为了使时间复杂度更小,我们可以使之扁平化(但好像正着搜没有什么作用,因为每次是删头结点,并不是连接两点),但若使用并查集的话,每次搜索还是要搜寻每个点的根节点,并且还要判断每一条边能不能走,这也一定会超时,那如果每次不遍历每一个点,那是否就能不超时呢?
其实要做到这一点也不难,我们不如反向思维,是不是从开头每次删一个点直至删完,就相当于从后面做每次加一个点直至补完,并且从结尾往前加点,那么每次符合条件的边就不可能变动(就不用考虑之前连接的两点是否连通),并且每一个节点的根就只会连到另一个节点上,扁平化就更能体现作用。
但现在还是没有解决遍历点的问题及遍历边的问题(重中之重,打起精神来,注意!)
遍历点的问题:是不是每加一个点,就相当于多了一个连通块,而每把两个根节点不相同的连通块相连就少了一个根节点,若要使整个图为一个环形,则整个图为一个连通块。
遍历边的问题:既然点是按先后顺序出现的,而边的出现是看两头的点是否出现,若按平常的话,一定要去搜索,在这里我们只需排序即可。我们先记录下每一个点出现的先后排名,然后记录下每一条边的两个端点,最后按照每条边的端点出现的先后排序即可(记得按每条边的最晚出现的点与对方做比较)。我们回到程序中,在搜的时候只要看当前的边是否符合条件,若符合,则把条的两端点的根相连,若不符合,则不往下继续搜
code:
1 #include<bits/stdc++.h> 2 #pragma GCC optimize(3) 3 const int N=200001; 4 using namespace std; 5 int n,m,tot; 6 int ver[N*2],nxt[N*2],head[N],f[N],k[N]; 7 int sum; 8 bool flag[N]; 9 bool ans[N]; 10 void inint(){ 11 freopen("light.in","r",stdin); 12 freopen("light.out","w",stdout); 13 } 14 inline int read(){ 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 17 while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 18 return x*f; 19 } 20 inline void write(int x) 21 { 22 if(x<0)x=-x,putchar('-'); 23 if(x>9)write(x/10); 24 putchar(x%10+'0'); 25 } 26 void add(int x,int y){ 27 ++tot; 28 ver[tot]=y; 29 nxt[tot]=head[x]; 30 head[x]=tot; 31 } 32 int find(int fa){ 33 if(f[fa]==fa)return fa; 34 return f[fa]=find(f[fa]); 35 } 36 int main() 37 { 38 //inint(); 39 n=read(),m=read(); 40 for(int i=1;i<=n;i++){ 41 f[i]=i; 42 } 43 for(int i=1,x,y;i<=m;i++){ 44 x=read(),y=read(); 45 add(x,y); 46 add(y,x); 47 } 48 for(int i=1;i<=n;i++){ 49 k[i]=read(); 50 } 51 for(int i=n;i>=1;i--){ 52 sum++; 53 flag[k[i]]=true; 54 for(int j=head[k[i]];j;j=nxt[j]){ 55 int y=ver[j]; 56 if(flag[y]&&find(y)!=find(k[i])){ 57 f[find(y)]=f[find(k[i])]; 58 sum--; 59 } 60 } 61 if(sum==1)ans[i]=true; 62 } 63 for(int i=1;i<=n;i++){ 64 if(ans[i])printf("YES\n"); 65 else printf("NO\n"); 66 } 67 return 0; 68 } 69 /* 70 4 3 71 1 2 72 2 3 73 3 4 74 3 75 4 76 1 77 2 78 */