zoukankan      html  css  js  c++  java
  • CF611H New Year and Forgotten Tree

    题意

    给定你一棵树,结点编号为 (1-n) 现在用问号的个数代表每个节点编号那个数字的长度,请你还原这一颗树,任意输出一个方案,可能无解。
    传送门
    (n<2 imes 10^5)

    思路

    首先位数相同的点之间的边随便连。

    因此剩下的就是一些不同色的点,要求 (a[i][j]=x) ,求连边方案(同色间不能连)。

    如果有解则一定存在一种方案,是将每种位数拿一个点出来,连成一个生成树,然后把其它的点连到生成树上的点。

    爆搜生成树的形态,然后用网络流求匹配判断是否存在方案。即对于 (a[i][j]) 可能是小 (i) 连向生成树中的 (j) 色或者反过来,两种加起来刚好满足时,对于两种情况的分配。

    输出答案(注意细节)

    #include <bits/stdc++.h>
    using std::queue;
    const int INF=200000,N=100;
    int n,a[100],f[100][100],w,fa[100],m,b[100],tot,s,t,last[N],to[N<<2],Next[N<<2],edge,flow[N<<2];
    int deep[N],sum,c[N];
    queue <int> q;
    char s1[100],s2[110];
    struct ed{
    	int x,y;
    }e[100];
    int cw(int x){
    	int cnt=0;
    	while (x) x=x/10,cnt++;
    	return cnt;
    }
    int find(int x){
    	if (fa[x]==x) return x;
    	fa[x]=find(fa[x]);
    	return fa[x];
    }
    bool p(){//判断是否是树 
    	for (int i=1;i<=w;i++) fa[i]=i;
    	for (int i=1;i<=m;i++){
    		if (b[i]==1){
    			int fx=find(e[i].x),fy=find(e[i].y);
    			if (fx==fy) return false;
    			fa[fx]=fy;
    		}
    	}
    	return true;
    }
    int cal(int x){return x&1?x+1:x-1;}
    void add(int x,int y,int z){
    	to[++edge]=y;
    	Next[edge]=last[x];
    	last[x]=edge;
    	flow[edge]=z;
    }
    void Add(int x,int y,int z){add(x,y,z),add(y,x,0);}
    bool bfs(){
    	memset(deep,0,sizeof(deep));
    	deep[s]=1;
    	q.push(s);
    	while (!q.empty()){
    		int x=q.front();
    		q.pop();
    		for (int i=last[x];i;i=Next[i])
    			if (flow[i] && !deep[to[i]]){
    				deep[to[i]]=deep[x]+1;
    				q.push(to[i]);
    			}
    	}
    	return deep[t];
    }
    int Dfs(int x,int now){
    	if (x==t) return now;
    	for (int i=last[x];i;i=Next[i]){
    		if (deep[to[i]]<=deep[x]) continue;
    		if (!flow[i]) continue;
    		int di=Dfs(to[i],std::min(now,flow[i]));
    		if (di){
    			flow[i]-=di;
    			flow[cal(i)]+=di;
    			return di;
    		}
    	}
    	return 0;
    }
    void Printf(){
    	for (int i=1;i<=m;i++)
    		if (b[i]) printf("%d %d
    ",c[e[i].x],c[e[i].y]);//主生成树 
    	for (int i=1;i<=w;i++)//同位数 
    		for (int j=c[i+1]-1;j>=c[i+1]-f[i][i];j--) printf("%d %d
    ",j,j-1);
    	for (int x=1;x<=w;x++){
    		int now=c[x]+1;
    		for (int i=last[x];i;i=Next[i])
    			if (to[i]-w>0 && to[i]-w<=m){
    				int u=e[to[i]-w].x+e[to[i]-w].y-x;
    				for (int j=now;j<now+flow[i];j++)
    					printf("%d %d
    ",c[u],j);
    				now=now+flow[i];
    			}
    	}
    }
    void solve(){
    	for (int i=1;i<=m;i++)
    		f[e[i].x][e[i].y]-=b[i];
    	memset(last,0,sizeof(last));
    	edge=0; 
    	for (int i=1;i<=w;i++)
    		Add(i,t,a[i]-1-f[i][i]);
    	for (int i=1;i<=m;i++)
    		if (f[e[i].x][e[i].y]){
    			Add(i+w,e[i].x,INF);
    			Add(i+w,e[i].y,INF);
    			Add(s,i+w,f[e[i].x][e[i].y]);
    		}
    	int ans=0;
    	while (bfs())
    		while (int di=Dfs(s,INF)) ans+=di;
    	if (ans==sum){
    		Printf();
    		exit(0);
    	}
    	for (int i=1;i<=m;i++)
    		f[e[i].x][e[i].y]+=b[i];
    }
    void dfs(int x,int y){//找生成树 
    	if (y==w-1){
    		if (p()) solve();
    		return;
    	}
    	if (x>m) return;
    	b[x]=0,dfs(x+1,y);
    	if(f[e[x].x][e[x].y])b[x]=1,dfs(x+1,y+1);
    }
    int main(){
    	scanf("%d",&n);
    	w=cw(n);
    	for (int i=1;i<n;i++){
    		scanf("%s%s",&s1,&s2);
    		int w1=strlen(s1),w2=strlen(s2);
    		if (w1>w2) std::swap(w1,w2);
    		f[w1][w2]++;
    	}
    	int j=1;
    	for (int i=1;i<w;i++,j=j*10) a[i]=j*9,c[i]=j;
    	if (w==1) a[w]=n;
    	else a[w]=n-j+1;
    	c[w+1]=n+1;
    	c[w]=j;
    	sum=n-1-(w-1);
    	for (int i=1;i<=w;i++)  
    		if (f[i][i]>=a[i]){
    			puts("-1");
    			return 0;
    		}else sum-=f[i][i];
    	m=0;
    	for (int i=1;i<=w;i++)
    		for (int j=i+1;j<=w;j++) e[++m]={i,j};
    	s=w+m+1,t=w+m+2;
    	dfs(1,0);
    	puts("-1");
    	return 0;
    }
    
  • 相关阅读:
    DBCC Page查看表和索引数据
    sp_configure
    学习
    OpenRowSet, OpenDataSource
    sp output
    SQL Server中使用CLR调用.NET方法
    SQL Server 2005五个有用的动态管理对象
    SQL显示执行语句信息
    接规则,每三个一组编一个号
    C# winform 与 flash as 的交互通讯
  • 原文地址:https://www.cnblogs.com/flyfeather6/p/12213027.html
Copyright © 2011-2022 走看看