B - Bitwise Exclusive-OR Sequence 染色
还以为是思维题结果是算法题,看来还是不能猜,要慎重的推理才可以 对于位运算来说,优先的思路就是按位处理,假设处理到第i位,第j个数没有被访问,那么我们就去访问这个数,给他染成1也好,染成0也好,按照规则相邻的点这一位上要满足规则,之后看看环是否满足条件,不满足直接退出;这样这个数所在的连通块就都满足了,然后再去遍历下一个连通块,每次ans都加上这一位的最小个数乘以(1<<i)就可以了
const ll N=7e5+5;
const ll inf=1e18;
const ll mod=1e9+7;
ll n,m,cnt,head[N],tmp[2];
bool vis[N],col[N],flag;
struct node
{
ll to,nxt,w;
}e[N*2];
void add(ll from,ll to,ll w)
{
e[++cnt].to=to;
e[cnt].w=w;
e[cnt].nxt=head[from];
head[from]=cnt;
}
void dfs(ll u,ll p,ll se){
tmp[se]++;col[u]=se;vis[u]=1;
for(int i=head[u];i;i=e[i].nxt){
ll j=e[i].to;
ll g=((e[i].w>>p)&1)^se;
if(vis[j]){
if(col[j]!=g){printf("-1\n");system("pause");exit(0);}
}
else{
dfs(j,p,g);
}
}
}
int main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
ll u,vv,w;
scanf("%lld%lld%lld",&u,&vv,&w);
add(u,vv,w);add(vv,u,w);
}
ll ans=0;
for(int i=0;i<30;i++){
tmp[0]=tmp[1]=0;
for(int j=1;j<=n;j++) vis[j]=col[j]=0;
for(int j=1;j<=n;j++){
if(!vis[j]) dfs(j,i,0);
ans+=min(tmp[0],tmp[1])*(1<<i);
tmp[0]=tmp[1]=0;
}
}
printf("%lld\n",ans);
system("pause");
return 0;
}
H - Line Graph Matching 并查集/无向图求割边
求L(G)的时候和G做对照看一下,发现只要连通块的边数是偶数就可以把边全选上,否则就要删除一条边;那么删除最小的那条边应该是最优的,但是如果这条最小的边是桥的话那么这个就不能删掉,因为这样的话断开的两个连通块还是奇数,那么还是要额外删掉两条边不是最优的,所以我们设f[i]为以i为根所对应的边的权值是多少,遍历时u==v(u是x的祖先,v是y的祖先)的条件下f[u]为0,那么就让f[u]=w,否则就加上这对边,陪完对f[u]=0,因为一条边只能用一次;u!=v的条件下如果!f[u]&&!f[v]说明都没有相应的权值,就让f[u]=w,如果其中一个是有权值的,那就让w和这条边配对,f[u]=0,如果都有权值,说明u--v这条边是一个桥,那么就让w和f[u],f[v]之间最大的配对,留下最小的那一个当桥就可以
2021 ICPC沈阳 H.Line Graph Matching(并查集+贪心)_lwz_159的博客-CSDN博客
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const ll N=7e5+5;
const ll inf=1e18;
const ll mod=1e9+7;
ll n,m,s[100005],f[100005];
ll findd(ll x){return x==s[x]?x:s[x]=findd(s[x]);}
struct node{
ll u,v,w;
bool operator<(const node &a) const{
return w>a.w;
}
}e[200005];
int main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) f[i]=0,s[i]=i;
for(int i=1;i<=m;i++) scanf("%lld%lld%lld",&e[i].u,&e[i].v,&e[i].w);
sort(e+1,e+m+1);
ll ans=0;
for(int i=1;i<=m;i++){
ll u=findd(e[i].u),v=findd(e[i].v);
if(u==v){
if(!f[u]) f[u]=e[i].w;
else ans+=f[u]+e[i].w,f[u]=0;
}
else{
s[v]=u;
if(!f[u]&&!f[v]) f[u]=e[i].w;
else if(!f[u]||!f[v]) ans+=e[i].w+f[u]+f[v],f[u]=0;
else ans+=e[i].w+max(f[u],f[v]),f[u]=min(f[u],f[v]);
}
}
printf("%lld\n",ans);
system("pause");
return 0;
}