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

    今天运气爆棚啊,写完调了下过了样例就直接一发入魂了,导致我立的flag倒了

    由于这里给出的数只有位数的区别,因此我们很容易想到把不同位数的分开来做

    我们给每个位数的数中选一个定为关键点,显然最后存在至少一种方案满足所有的边都经过至少一个关键点

    那么我们考虑先把所有关键点连起来,由于当(nle 2 imes 10^5)时不同的位数只有(6)位,因此直接爆搜一下树的形态即可

    接下来就考虑对于每条边((x,y))是从(x)的关键点连向(y)还是从(y)的关键点连向(x)了,我们可以把这看做一个网络流模型:

    • (frac{m(m+1)}{2})((x,y))边的关系看做左边的点,源点向每个点连未确定的边数(总边数减去关键点之间边数)为容量的边
    • (m)种点看做右边的点,每个点向汇点连该位数的非关键点的点数为容量的边
    • 左边的点((x,y))向右边的(x,y)连与源点到((x,y))的容量相同的边

    由于这里的数据范围极小,因此保证正确性即可,复杂度什么的都是随便跑

    PS:好像有Hall定理的做法比这个简洁的多,然后好像还有并查集的神仙做法,这个就跟个暴力一样的说

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define RI register int
    #define CI const int&
    using namespace std;
    typedef pair <int,int> pi;
    const int N=10;
    int n,m,x,y,id[N][N],L[N],R[N],p[N],ans,fa[N],c[N][N],r[N][N]; char s[N];
    namespace NF //Network Flow
    {
        const int N=100,M=10000,INF=1e9;
    	struct edge
    	{
    		int to,nxt,v;
    	}e[M]; int cnt=1,head[N],cur[N],q[N],dep[N],s,t;
        inline void addedge(CI x,CI y,CI z)
        {
            e[++cnt]=(edge){y,head[x],z}; head[x]=cnt;
            e[++cnt]=(edge){x,head[y],0}; head[y]=cnt;
        }
    	#define to e[i].to
        inline bool BFS(void)
        {
            RI H=0,T=1; memset(dep,0,t+1<<2); q[dep[s]=1]=s;
            while (H<T)
            {
                int now=q[++H]; for (RI i=head[now];i;i=e[i].nxt)
                if (e[i].v&&!dep[to]) dep[to]=dep[now]+1,q[++T]=to;
            }
            return dep[t];
        }
        inline int DFS(CI now,CI tar,int dis)
        {
            if (now==tar) return dis; int ret=0;
            for (RI& i=cur[now];i&&dis;i=e[i].nxt)
            if (e[i].v&&dep[to]==dep[now]+1)
            {
                int dist=DFS(to,tar,min(dis,e[i].v));
                dis-=dist; ret+=dist; e[i].v-=dist; e[i^1].v+=dist;
            }
            if (!ret) dep[now]=0; return ret;
        }
    	#undef to
        inline int Dinic(int ret=0)
        {
            while (BFS()) memcpy(cur,head,t+1<<2),ret+=DFS(s,t,INF); return ret;
        }
        inline void clear(void)
        {
        	cnt=1; for (RI i=s;i<=t;++i) head[i]=0;
        }
    };
    inline void check(void)
    {
    	RI i,j,k,t; for (i=1;i<=m;++i) for (j=i;j<=m;++j) r[i][j]=c[i][j];
    	for (i=2;i<=m;++i)
    	{
    		bool flag=0; int c=0; for (j=i;c<=m&&!flag;++c,j=fa[j])
    		if (j==1) flag=1; if (!flag) return; int x=i,y=fa[i];
    		if (x>y) swap(x,y); if (r[x][y]) --r[x][y]; else return;
    	}
    	for (NF::clear(),NF::s=0,NF::t=m*(m+1)/2+m+1,i=1;i<=m;++i) for (j=i;j<=m;++j)
    	{
    		NF::addedge(NF::s,id[i][j],r[i][j]);
    		NF::addedge(id[i][j],m*(m+1)/2+i,r[i][j]);
    		if (i!=j) NF::addedge(id[i][j],m*(m+1)/2+j,r[i][j]);
    	}
    	int sum=0; for (i=1;i<=m;++i) NF::addedge(m*(m+1)/2+i,NF::t,R[i]-L[i]),sum+=R[i]-L[i];
    	if (NF::Dinic()!=sum) return;
    	for (i=2;i<=m;++i) printf("%d %d
    ",L[i],L[fa[i]]); for (i=1;i<=m;++i) p[i]=L[i];
    	for (i=1;i<=m;++i) for (j=i;j<=m;++j) for (k=NF::head[id[i][j]];k;k=NF::e[k].nxt)
    	if (NF::e[k].to!=NF::s) for (t=1;t<=r[i][j]-NF::e[k].v;++t)
    	printf("%d %d
    ",++p[NF::e[k].to-m*(m+1)/2],L[i+j-(NF::e[k].to-m*(m+1)/2)]); exit(0);
    }
    inline void DFS(CI now=2)
    {
    	if (now>m) return check(); for (RI i=1;i<=m;++i)
    	if (i!=now) fa[now]=i,DFS(now+1);
    }
    int main()
    {
    	RI i,j; for (scanf("%d",&n),x=1;x<=n;x*=10) ++m,L[m]=x,R[m]=min(x*10-1,n);
    	for (x=0,i=1;i<=m;++i) for (j=i;j<=m;++j) id[i][j]=++x;
    	for (i=1;i<n;++i) 
    	{
    		scanf("%s",s+1); x=strlen(s+1); scanf("%s",s+1); y=strlen(s+1);
    		if (x>y) swap(x,y); ++c[x][y];
    	}
    	return DFS(),puts("-1"),0;
    }
    
    辣鸡老年选手AFO在即
  • 相关阅读:
    js将手机号中间四位变成*
    js判断浏览器客户端类型
    vue项目涉及到的setInterval
    MYSQL 总结——2
    MySQL补充
    PyCharm软件安装
    MYSQL 总结——1
    linux系统通过ssh拉取gitee项目 设置权限
    tp5开源的后台管理系统
    window下Python安装
  • 原文地址:https://www.cnblogs.com/cjjsb/p/13878902.html
Copyright © 2011-2022 走看看