• CF1054G New Road Network


    现在你要构造一棵(n)个点的树。

    题目给出(m)个集合,要求每个集合内的点在构造出的树中形成连通块。

    (n,mle 2000)


    (A_i)为包含(i)的集合的集合。

    如果某个集合只在一个(A_i)中出现过,则删去这个集合。先进行这个操作。

    如果有解,对于一个叶子节点(u),其父亲为(v)。可以发现此时一定有(A_usubseteq A_v)

    反过来,如果有解,任意找到一对((u,v))满足(A_usubseteq A_v),把(u)的父亲钦定为(v)。然后删去(u),并且删去只在一个(A_i)中出现过的集合,变成子问题继续搞下去。这样最终一定能找到一个解。

    如果这样找不到解,说明无解。

    模拟这个过程即可,可以做到(O(frac{n^2m}{omega}))的时间。

    另一个不太好证明的做法:造一个无向图,((u,v))边权为(|A_u igcap A_v|),做最大生成树。直接判断这个生成树是否合法,如果不合法一定无解。


    using namespace std;
    #include <bits/stdc++.h>
    #define N 2005
    int n,m;
    char str[N][N];
    int c[N];
    bitset<N> b[N];
    int e[N][N];
    pair<int,int> ed[N];
    int cnt;
    pair<int,int> q[N*N];
    bool vis[N];
    bool doit(){
    	int head=1,tail=0;
    	for (int i=1;i<=n;++i)
    		for (int j=1;j<=n;++j)
    			if (i!=j && (b[i]&b[j])==b[i])
    				e[i][j]=1,q[++tail]={i,j};
    			else
    				e[i][j]=0;
    	memset(vis,0,sizeof(bool)*(n+1));
    	cnt=0;
    	while (head<=tail && cnt<n-1){
    		int u=q[head].first,v=q[head].second;
    		++head;
    		if (vis[u] || vis[v])
    			continue;
    		ed[++cnt]={u,v};
    		vis[u]=1;
    		for (int i=1;i<=m;++i)
    			if (b[u][i]){
    				if (--c[i]==1)
    					b[v][i]=0;
    			}
    		for (int i=1;i<=n;++i)
    			if (!vis[i] && i!=v && !e[v][i] && (b[v]&b[i])==b[v])
    				e[v][i]=1,q[++tail]={v,i};
    	}
    	return cnt==n-1;
    }
    int main(){
    //	freopen("in.txt","r",stdin);
    	int T;
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d%d",&n,&m);
    		for (int i=1;i<=n;++i)
    			b[i].reset();
    		for (int i=1;i<=m;++i){
    			scanf("%s",str[i]+1);
    			c[i]=0;
    			for (int j=1;j<=n;++j)
    				c[i]+=(str[i][j]=='1');
    			if (c[i]>1)
    				for (int j=1;j<=n;++j)
    					if (str[i][j]=='1')
    						b[j][i]=1;
    		}
    		if (!doit())
    			printf("NO
    ");
    		else{
    			printf("YES
    ");
    			for (int i=1;i<n;++i)
    				printf("%d %d
    ",ed[i].first,ed[i].second);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    linux 文件时间
    linux命令学习 touch
    linux命令学习 cp
    Linux命令学习 mv
    SpringMVC mvc详解
    JDBC原生态代码
    java中静态方法中调用非静态方法的详解
    Spring技术详解
    Spring中的 BeanFactory和 ApplicationContext的区别与解释
    java多线程编程相关技术
  • 原文地址:https://www.cnblogs.com/jz-597/p/14453748.html
Copyright © 2020-2023  润新知