19十一高端峰会——金华站 T2 图论

Posted white-star

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19十一高端峰会——金华站 T2 图论相关的知识,希望对你有一定的参考价值。

第二道构造题

不把金华考生当人系列。

题解OJ上有,这里不赘述

关键是此题代码如果写的好只需50行,写的不好可能要200行。

这里给出100行的丑陋代码(懒人必备STL vector,省了很多代码)

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))

const int inf=0x3f3f3f3f,N=1e3+10;

int n,f[N],du[N],tot;
char s[N][N];
bool g[N][N],e[N][N];
bool vis[N];
vector<int>blo[N];

void read(int &x){
    x=0;char c=getchar(),f=1;
    while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); }
    while(isdigit(c)){ x=x*10+c-'0'; c=getchar(); }
    x*=f;
}
inline int find(int x){ return f[x]=f[x]==x?x:find(f[x]); }
void merge(int x,int y){
    int fx=find(x),fy=find(y);
    if(fx==fy) return;
    g[x][y]=g[y][x]=1;
    f[fx]=fy;
}

void dfs(int u){
    vis[u]=1;
    go(v,1,n){
        if(!g[u][v]||vis[v]) continue;
        dfs(v);
        if(du[v]&1){
            ++du[v],++du[u];
            e[u][v]=e[v][u]=1;
        }
    }
}
void fail(){ puts("No"),exit(0); }
void suc(){
    puts("Yes");
    go(i,1,n){
        go(j,1,n)
            printf("%d",e[i][j]||s[i][j]);
        puts("");
    }
    exit(0);
}

void Dfs(int u){
    blo[tot].push_back(u);
    vis[u]=1;
    go(v,1,n)
        if((s[u][v]||e[u][v])&&!vis[v])
            Dfs(v);
}

int main(){
    //freopen("input.txt","r",stdin);
    read(n);
    go(i,1,n) scanf("%s",s[i]+1),f[i]=i;
    go(i,1,n) go(j,1,n) s[i][j]-='0';
    go(i,1,n) go(j,i+1,n) s[i][j]?++du[i],++du[j]:0;
    go(i,1,n) go(j,i+1,n) if(find(i)!=find(j)&&!s[i][j]) merge(i,j);
    //建出补图的最小生成树 
    go(i,1,n)
        if(!vis[i]){
            dfs(i);
            if(du[i]&1) fail();
        }
    mem(vis,0);
    go(i,1,n) if(!vis[i]) ++tot,Dfs(i);
    int x,y;
    if(tot==1) suc();
    else{
        if(tot>2){
            go(i,1,tot-1){
                x=blo[i][0],y=blo[i+1][0];
                e[x][y]=e[y][x]=1;
            }
            x=blo[1][0],y=blo[tot][0];
            e[x][y]=e[y][x]=1;
            suc();
        }
        else{
            if(blo[1].size()>blo[2].size()) swap(blo[1],blo[2]);
            if(blo[1].size()>1){
                go(i,0,1)
                    go(j,0,1)
                        e[blo[1][i]][blo[2][j]]=e[blo[2][j]][blo[1][i]]=1;
                suc();
            }
            else{
                x=blo[1][0];
                for(int k=0;k<blo[2].size();++k)
                    for(int l=k+1;l<blo[2].size();++l){
                        int i=blo[2][k],j=blo[2][l];
                        if(!s[i][j]){
                            e[i][j]^=1;e[j][i]^=1;
                            e[x][i]=e[i][x]=e[x][j]=e[j][x]=1;
                            suc();
                        }
                    }
            }
        }
    }
    fail();
    return 0;
}

然后是xuyuan大佬包含智慧的并查集代码,十分精妙,只需50行

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,cc,d[N],fa[N],sz[N],q[N],vis[N],e[N][N],g[N][N];char s[N][N];
int fnd(int x){return fa[x]==x?x:fa[x]=fnd(fa[x]);}
void dfs(int x)
{
    vis[x]=1;
    for(int y=1;y<=n;y++)if(!vis[y]&&!e[x][y])
    {
        dfs(y);
        if(d[y]&1){d[x]++;d[y]++;g[x][y]=g[y][x]=1;}
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)e[i][j]=s[i][j]-'0',d[i]+=e[i][j];
    for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1;
    for(int i=1;i<=n;i++)if(!vis[i])dfs(i);
    for(int i=1;i<=n;i++)if(d[i]&1){puts("No");return 0;}
    for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)if((e[i][j]||g[i][j])&&fnd(i)!=fnd(j)){int x=fnd(i),y=fnd(j);fa[x]=y;sz[y]+=sz[x];}
    for(int i=1;i<=n;i++)if(fa[i]==i)q[++cc]=i;
    if(cc>2){for(int i=1;i<=cc;i++){int x=q[i],y=q[i%cc+1];g[x][y]=g[y][x]=1;}}
    else if(cc==2)
    {
        int u=q[1],v=q[2],x=-1,y=-1;
        if(sz[v]==1)swap(u,v);
        if(sz[u]>=2)
        {
            for(int i=1;i<=n;i++)if(fnd(i)==u&&i!=u)x=i;
            for(int i=1;i<=n;i++)if(fnd(i)==v&&i!=v)y=i;
            g[u][v]=g[v][u]=g[u][y]=g[y][u]=g[x][v]=g[v][x]=g[x][y]=g[y][x]=1;
        }
        else
        {
            for(int i=1;i<=n;i++)if(i!=u)for(int j=i+1;j<=n;j++)if(j!=u&&!e[i][j]){x=i;y=j;}
            if(x==-1){puts("No");return 0;}
            g[x][y]^=1;g[y][x]^=1;g[u][x]=g[x][u]=g[u][y]=g[y][u]=1;
        }
    }
    puts("Yes");
    for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)putchar((e[i][j]||g[i][j])?'1':'0');puts("");}
    return 0;
}

以上是关于19十一高端峰会——金华站 T2 图论的主要内容,如果未能解决你的问题,请参考以下文章

zr2019暑期高端峰会AB组十测

浙江金华 图论整理

金华集训 - 图论填坑 连载中......

19CSP-S十一集训三地联考—众神归位

SDUT 2498 数据结构实验之图论十一:AOE网上的关键路径

19CSP-S十一集训三地联考—众神归位 题解总结