ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF739D Recover a functional graph

2020-01-27 22:01:18  阅读:277  来源: 互联网

标签:include return CF739D graph 距离 环长 int Recover 补齐


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");
}

标签:include,return,CF739D,graph,距离,环长,int,Recover,补齐
来源: https://www.cnblogs.com/cjoierShiina-Mashiro/p/12237008.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有