前言
传送门 : https://atcoder.jp/contests/abc218/tasks/abc218_e
思路
看完题目发现就是跑一个最小生成树
但是有负权,不能直接跑
因此我们不如反过来想,将负权边加入到集合当中
尽可能的少加入正权边,这样又可以安心的跑最小生成树了
CODE
#include <bits/stdc++.h>
using namespace std;
using ll =long long;
const int INF = 0x3f3f3f3f;
const int N = 2e5+10;
const int M = 4e5+10;
int p[N];
int n,m;
struct Edge
{
int a, b, w;
bool operator< (const Edge &W)const
{
return w < W.w;
}
} edges[M];
int find(int x)
{
if(x!=p[x])
return p[x] =find(p[x]);
return p[x];
}
ll kruskal()
{
sort(edges+1, edges + m+1);
ll res = 0;
for (int i = 1; i <= m; i ++ )
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a), b = find(b);
if(a == b)
{
if(w<0)
res+=w;
continue;
}
p[a] =b;
res+=w;
}
return res;
}
void solve()
{
cin>>n>>m;
ll sum = 0;
for(int i=1;i<=n;i++)
p[i]=i;
for(int i=1; i<=m; i++)
{
int a,b,k;
cin>>a>>b>>k;
edges[i]={a,b,k};
sum+=k;
}
cout<<sum-kruskal();
}
int main()
{
ios::sync_with_stdio(false);
solve();
return 0;
}