题目内容
[20241017] Min-max 容斥
小 M 在\(\pi\) 岁时学会了 min-max 容斥。
给定一张 \(n\)个点\(m\)条边的边带权简单连通无向图。现需要将其的每个结点染成黑色或白色。
定义两个结点的距离为这两点间所有路径的边权之和的最小值。
对于一种染色的方式,定义一个结点\(u\) 的代价为:对于所有与\(u\) 异色的点\(v\) , \(u\)和\(v\) 的距离的最小值。如果不存在这样的点,那么代价为\(10^{100}\) 。
该染色方式的代价为所有结点的代价的最大值。
您需要构造一种染色方式,使其最小化代价。
\(2\le n\le 5\times 10^5,n-1\le m\le\min(5\times 10^5,\frac{n(n-1)}2),1\le w\le 10^9,1\le u,v\le n\)
思路
最小生成树。
首先考虑当输入为一棵树的情况:显然,为了使代价最小,我们应该采取“交替染色”的策略,即每一个旁边的都跟他本身不一样。
所以我们可以想到,我们可以召唤一棵树,为了使最大的最小,显然我们应该召唤最小生成树。
然后就没有然后了。
代码
#include<bits/stdc++.h>
//#pragma GCC optimize("O3,unroll-loops")感谢章鱼的核聚变
//#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")让我WA 0还找不到问题
using namespace std;
struct bi{int u,v,w;
}a[500004];
int n,m,i,j,x,y,z,c[500004],p[500004],ans;
vector<int> v[500004];
void dfs(int x,int y){c[x]=y;for(int i=0;i<v[x].size();i++){if(c[v[x][i]]) continue;dfs(v[x][i],3-y);}return ;
}
bool cmp(bi q,bi w){return q.w<w.w;
}
int f(int x){if(p[x]==x) return x;return p[x]=f(p[x]);
}
int main()
{
// freopen("A4.in","r",stdin);
// freopen("A4.out","w",stdout);scanf("%d%d",&n,&m);for(i=1;i<=n;i++) p[i]=i;for(i=1;i<=m;i++) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);sort(a+1,a+1+m,cmp);for(i=1;i<=m;i++){if(f(a[i].u)==f(a[i].v)) continue;p[f(a[i].u)]=f(a[i].v);v[a[i].u].push_back(a[i].v);v[a[i].v].push_back(a[i].u);}dfs(1,1);for(i=1;i<=n;i++) printf("%d",c[i]-1);
}