zoukankan      html  css  js  c++  java
  • CF739D Recover a functional graph

    Link
    首先把所有的按环长分类,那么我们需要做的就是满足以下几个条件:
    (1.)每个环长的到环距离为(0)的点的个数应该是环长的倍数。当然只需要在最低限度下将其补齐即可。
    (2.)每个环长的到环距离必须是连续的。
    (3.)必须要有某个环去接受环长为(?)的距离最长的点。
    那么我们可以枚举把环长为(?)的距离最长的点放在哪个长度的环,然后二分图匹配补齐(1,2)两条限制,多余出的点随便搞搞就完事了。

    #include<cstdio>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    const int N=307;
    int max(int a,int b){return a>b? a:b;}
    int n,m,mx,len[N],dis[N],fa[N],x[N],y[N],cnt[N],mxd[N],e[N][N],vis[N],L[N],R[N],mat[N];
    std::vector<int>vec[N];char s1[5],s2[5];
    int dfs(int u)
    {
        for(int v=1;v<=m;++v) if(e[u][v]&&!vis[v]&&!R[v]) if(vis[v]=1,!mat[v]||dfs(mat[v])) return mat[v]=u,1;
        return 0;
    }
    int check(int p)
    {
        memset(e,0,sizeof e),memset(L,0,sizeof L),memset(R,0,sizeof R),memset(mat,0,sizeof mat),m=0;
        for(int i=1;i<=n;++i)
    	if(~mxd[i]||i==p)
    	{
    	    int c=cnt[i],l=mxd[i];
    	    if(i==p) c=max(c,i),l=max(l,mx);
    	    for(int j=1;j<=c;++j)
    	    {
    		if(++m>n) return 0;
    		x[m]=i,y[m]=0;
    	    }
    	    for(int j=1;j<=l;j++)
    	    {
    		if(++m>n) return 0;
    		x[m]=i,y[m]=j;
    	    }
    	}
        int ans=0;
        for(int i=1;i<=n;++i)
    	for(int j=1;j<=m;++j)
    	{
    	    e[i][j]=(len[i]==x[j]||!~len[i])&&(dis[i]==y[j]||!~dis[i]);
    	    if(len[i]==x[j]&&dis[i]==y[j]&&!L[i]&&!R[j]) L[i]=R[j]=1,mat[j]=i,++ans;
    	}
        for(int i=1;i<=n;++i) if(!L[i]) memset(vis,0,sizeof vis),ans+=dfs(i);
        return ans==m;
    }
    void print(int p)
    {
        for(int i=1;i<=m;++i) len[mat[i]]=x[i],dis[mat[i]]=y[i];
        for(int i=1;i<=n;++i)
    	if(!~len[i]) if(dis[i]<=0) dis[i]=0,len[i]=1; else len[i]=p;
    	else if(!~dis[i]) dis[i]=1;
        for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(len[i]==len[j]&&dis[i]==dis[j]+1) {fa[i]=j;break;}
        for(int i=1;i<=n;++i)
    	if(!dis[i])
    	{
    	    vec[len[i]].push_back(i);
    	    if((int)vec[len[i]].size()==len[i])
    	    {
    		for(int j=0;j<len[i];++j) fa[vec[len[i]][j]]=vec[len[i]][(j+1)%len[i]];
    		vec[len[i]].clear();
    	    }
    	}
        for(int i=1;i<=n;++i) printf("%d ",fa[i]);
    }
    int main()
    {
        scanf("%d",&n),memset(mxd,-1,sizeof mxd);
        for(int i=1;i<=n;++i)
        {
    	scanf("%s%s",s1,s2),dis[i]=s1[0]=='?'? -1:std::atoi(s1),len[i]=s2[0]=='?'? -1:std::atoi(s2);
    	if(~len[i])
    	{
    	    mxd[len[i]]=max(mxd[len[i]],max(dis[i],0));
    	    if(!dis[i]) ++cnt[len[i]];
    	}
    	else mx=max(mx,dis[i]);
        }
        for(int i=1;i<=n;++i) cnt[i]=max(1,(cnt[i]+i-1)/i)*i;
        for(int i=1;i<=n;++i) if(check(i)) return print(i),0;
        puts("-1");
    }
    
  • 相关阅读:
    Windows Server 2008 R2域控组策略设置禁用USB
    Windows Server 2008 R2组策略设置计算机配置和用户配置
    Windows Server 2008 R2父域管理员与子域管理员相互登录访问
    转载:如何处理浏览器的断网情况?
    转载:浏览器缓存库设计总结(localStorage/indexedDB)
    手写启动一个本地服务器的命令行工具
    Node.js-核心模块-zlib
    使用console.log打印公司招聘信息和字符画
    转载:准备刷 leetcode 了,才发现自己连时间复杂度都不懂
    转载:前端通信那些事儿
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12237008.html
Copyright © 2011-2022 走看看