zoukankan      html  css  js  c++  java
  • bzoj3237[Ahoi2013] 连通图

    题目链接:bzoj3237

    题目大意:

    给一个N个点M条边的无向图。有K个询问,每个询问描述一个边集,你要输出若该边集从原图中删除,该图还是否连通。
    是,则输出Conected;否,则输出Disconnected


    题解:

    cdq分治+并查集

    首先把所有没有影响的边都建出来

    分治过程:

    1、把左边没有右边有的边建出来

    2、分治左边

    3、把并查集恢复至初始的样子

    4、把右边没有左边有的边建出来

    5、分治右边

    每次建的边数为这个区间内的集合中的边数,是一个与n无关的量,所以复杂度是正确的

    O(qclogqc)

    时间戳的思路不错

    #cp http://blog.csdn.net/u012288458/article/details/51377391

    目测这个大大看的CA爷写的,居然能看懂%%%

    判断一个图是否连通,只要看看被删除的边集中一边上的两点是否连通(用并查集判断)就好了。

    恢复并查集的话就是在修改前用栈记录,恢复的时候改回来就好了

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define N 100010
    #define M 200010 
    
    struct node
    {
    	int x,y,tim;
    }a[M];
    struct ques
    {
    	int num,c[5];
    }q[N];
    int tim,tp;bool ans[N];
    int fa[N],sta1[N*50],sta2[N*50];
    int ffind(int x)
    {
    	if (fa[x]!=x) 
    	{
    		int y=fa[x];
    		sta1[++tp]=x;sta2[tp]=y;
    		fa[x]=ffind(fa[x]);
    	}
    	return fa[x];
    }
    void solve(int l,int r)
    {
    	int now=tp,i,j;
    	if (l==r)
    	{
    		bool bk=true;
    		for (i=1;i<=q[l].num;i++)
    		 if (ffind(a[q[l].c[i]].x)!=ffind(a[q[l].c[i]].y)) {bk=false;break;}
    		ans[l]=bk;
    		while (tp!=now) fa[sta1[tp]]=sta2[tp],tp--;
    		return;
    	}
    	int mid=(l+r)>>1;
    	tim++;
    	for (i=l;i<=mid;i++)
    	 for (j=1;j<=q[i].num;j++)
    	  a[q[i].c[j]].tim=tim;
    	
    	for (i=mid+1;i<=r;i++)
    	 for (j=1;j<=q[i].num;j++)
    	  if (a[q[i].c[j]].tim!=tim)
    	  {
    		  int f1=ffind(a[q[i].c[j]].x),f2=ffind(a[q[i].c[j]].y);
    		  if (f1!=f2)
    		  {
    			  sta1[++tp]=f1;sta2[tp]=fa[f1];
    			  fa[f1]=f2;
    		  }
    	  }
    	solve(l,mid);
    	while (tp!=now) fa[sta1[tp]]=sta2[tp],tp--;
    	tim++;
    	for (i=mid+1;i<=r;i++)
    	 for (j=1;j<=q[i].num;j++)
    	  a[q[i].c[j]].tim=tim;
    	
    	for (i=l;i<=mid;i++)
    	 for (j=1;j<=q[i].num;j++)
    	  if (a[q[i].c[j]].tim!=tim)
    	  {
    		  int f1=ffind(a[q[i].c[j]].x),f2=ffind(a[q[i].c[j]].y);
    		  if (f1!=f2)
    		  {
    			  sta1[++tp]=f1;sta2[tp]=fa[f1];
    			  fa[f1]=f2;
    		  }
    	  }
    	
    	solve(mid+1,r);
    }
    int main()
    {
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	int n,m,i,j,k;
    	scanf("%d%d",&n,&m);
    	for (i=1;i<=n;i++) fa[i]=i;
    	for (i=1;i<=m;i++) {scanf("%d%d",&a[i].x,&a[i].y);a[i].tim=0;}
    	scanf("%d",&k);
    	tim=1;tp=0;
    	for (i=1;i<=k;i++)
    	{
    		scanf("%d",&q[i].num);
    		for (j=1;j<=q[i].num;j++)
    		{
    			scanf("%d",&q[i].c[j]);
    			a[q[i].c[j]].tim=tim;
    		}
    	}
    	for (i=1;i<=m;i++)
    	  if (a[i].tim!=tim)
    	  {
    		  int f1=ffind(a[i].x),f2=ffind(a[i].y);
    		  if (f1!=f2) fa[f1]=f2;
    	  }
    	solve(1,k);
    	for (i=1;i<=k;i++) if (ans[i]) printf("Connected
    ");else printf("Disconnected
    ");
    	return 0;
    }


  • 相关阅读:
    js格式化金额(保留指定小数位,不进行四舍五入每隔三位添加‘,’)
    原生js ajax下载excel,pdf,兼容ie8
    css文本超出显示点点....
    Vue 响应式删除 Vue.delete( target, propertyName/index )
    java报错:com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize out of START_ARRAY token
    Vue 神奇的BUG
    vue 诡异问题
    str.indexOf('') == 0
    vue 绑定style,class
    uniapp 时间轴
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527808.html
Copyright © 2011-2022 走看看