2021 年百度之星·程序设计大赛 - 初赛二 1003 魔怔(并查集,联通性,欧拉回路)
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021 年百度之星·程序设计大赛 - 初赛二 1003 魔怔(并查集,联通性,欧拉回路)相关的知识,希望对你有一定的参考价值。
problem
solution
- 发现除了起点和终点,剩下所有点周围的边都会被恰经过偶数次,所以这些点初始连向了偶数条白边。
- 考虑由白边连接形成的图,每个连通块中度数为奇数的点一定为偶数个。
- 所以起点所在连通块最多有两个点度数为奇数,且包含起点,不包含起点的连通块不能有点度数为奇数。(或者由欧拉回路的性质可得,如果有大于两个度为奇数的点一定是不能完成任务的)
- 所以每个包含白边的连通块都可以一笔画,每条白边都恰经过一次且不会经过黑边。答案即为 白边个数 +2 ( 包含白边或包含起点的连通块个数 -1)。
//没补完.jpg
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1010;
int fa[maxn+10];
void init(int n){for(int i = 1; i <= n; i++)fa[i]=i;}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void merge(int x, int y){x=find(x);y=find(y);if(x!=y)fa[x]=y;}
int e[maxn][maxn], in[maxn];
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T; cin>>T;
while(T--){
memset(e,0,sizeof(e));
memset(in,0,sizeof(in));
int n, rt; cin>>n>>rt;
int cnt = 0; init(n);
for(int i = 2; i <= n; i++){
string s; cin>>s;
for(int j = 0; j < i-1; j++){
e[i][j+1] = e[j+1][i]= s[j]-'0';
if(e[i][j+1]==0){
cnt++;
in[i]++; in[j+1]++;//累加度数
merge(i,j+1);
}
}
}
//cout<<cnt+2<<"\\n";
LL ans = 0, sum = 0, ok=0;
map<int,int>mp;
for(int i = 1; i <= n; i++){
if(in[i]%2==1)ans++;
sum += in[i];
if(in[i]){
int s = find(i);
if(mp[s]==0){ok++; mp[s]=1;}
}
}
if(sum==0){cout<<"0\\n"; continue;}
sum = sum/2+(ok-1)*2;
if(ans>2){cout<<"-1\\n"; continue;}
else{
if(in[rt]){//在
if(in[rt]%2==0){//偶数
if(ans)cout<<"-1\\n";
else cout<<sum<<"\\n";
}else{//奇数
cout<<sum<<"\\n";
}
}else{//不在
if(ans==0)cout<<sum+2<<"\\n";
else cout<<"-1\\n";
}
}
continue;
for(int i = 1; i <= n; i++){
for(int j=1; j <= n; j++)cout<<e[i][j]<<" ";
cout<<"\\n";
}
}
return 0;
}
以上是关于2021 年百度之星·程序设计大赛 - 初赛二 1003 魔怔(并查集,联通性,欧拉回路)的主要内容,如果未能解决你的问题,请参考以下文章
2021 年百度之星·程序设计大赛 - 初赛二 1005 水题(贪心结论)
2021 年百度之星·程序设计大赛 - 初赛二 1001 签到(找规律,快速幂)