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 图论的主要内容,如果未能解决你的问题,请参考以下文章