码迷,mamicode.com
首页 > 其他好文 > 详细

CF739D Recover a functional graph

时间:2020-01-27 23:59:23      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:recover   print   const   void   sizeof   for   class   puts   cti   

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

CF739D Recover a functional graph

标签:recover   print   const   void   sizeof   for   class   puts   cti   

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12237008.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!