1013 Image Segmentation (35 分)
解题思路:
首先是:The dissimilarity D(C1,C2) of any two components C1 and C2 is larger than the confidence H of any of C1 and C2.这句话的意思是这句话不是D(C1,C2)>H(C1)&&D(C1,C2)>H(C2)而是D(C1,C2)>H(C1)||D(C1,C2)>H(C2),不然样例解释不通了。
然后我们可以思考,如果从零实现克鲁斯卡尔,这样的话对于当前寻找的边连着的点a,b,我们可以判断,假设a和b连起来之后是否能断开,即通过维护好的a,b集合的最小生成树的最大边以及元素个数直接判断, 如果能断开,就说明a和b不能加到一个集合的,如果不能,就将a和b加到一个集合并修护点的信息。可以这么想:即使你把他们连起来了,后续也一定会存在一个方法使得a和b断开。
通过这样的方法可以保证,在遍历已有边的所有情况下,能连起来的集合全部连起来了,保证了D(C1,C2)>H(C1)||D(C1,C2)>H(C2),也保证了而其他原本没有的边属于无穷大,显然满足上式。
至于维护信息的方法:
就在每次合并集合的时候将子集合的信息传递给父集合就好
代码:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define pb push_back
#define G 6.67430*1e-11
#define rd read()
#define pi 3.1415926535
using namespace std;
const ll mod = 1e9 + 7;
const int MAXN = 30000005;
const int MAX2 = 300005;
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch>'9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
#define int ll
struct ss
{
int father;
int num;
int max;
}v[1005];
int find(int r) { return v[r].father == r ? r : v[r].father = find(v[r].father); }
int c;
void join(int x, int y, int value)
{
int fx = find(x), fy = find(y);
if (fx != fy)
{
ll C1 = v[fx].max * v[fx].num + c;
ll C2 = v[fy].max * v[fy].num + c;
if (value * v[fx].num <= C1 && value * v[fy].num <= C2)
{
v[fx].father = fy;
v[fy].max = max({ v[fx].max, v[fy].max,value });
v[fy].num += v[fx].num;
}
}
}
struct s
{
int a, b, weight;
}e[1005];
bool cmp(s a, s b) { return a.weight < b.weight; }
bool cmp2(vector<int> a, vector<int> b) { return a[0] < b[0]; }
vector<int> ans[1005];
vector<vector<int>> a;
signed main()
{
int n = rd, m = rd;
c = rd;
for (int i = 0; i < n; i++)
{
v[i].father = i;
v[i].max = 0;
v[i].num = 1;
}
for (int i = 0; i < m; i++)
{
e[i].a = rd;
e[i].b = rd;
e[i].weight = rd;
}
sort(e, e + m, cmp);
for (int i = 0; i < m; i++)
{
join(e[i].a, e[i].b, e[i].weight);
}
for (int i = 0; i < n; i++)
{
ans[find(i)].push_back(i);
}
for (int i = 0; i < n; i++)
{
if (ans[i].size())a.push_back(ans[i]);
}
sort(a.begin(), a.end(), cmp2);
for (int i = 0; i < a.size(); i++)
{
if (i)cout << endl;
for (int j = 0; j < a[i].size(); j++)
{
if (j)cout << ' ';
cout << a[i][j];
}
}
return 0;
}