This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct unionFind{
int par[100002];
void init(int _n){
for(int i=0; i<=_n; i++) par[i]=i;
}
int find(int x){
if(x==par[x]) return x;
return par[x] = find(par[x]);
}
void merge(int x, int y){
x = find(x), y = find(y);
par[x] = y;
}
} dsu, dsu2;
struct Edge{
int x, y; ll z;
Edge(){}
Edge(int x, int y, ll z): x(x), y(y), z(z){}
bool operator<(const Edge &r)const{
return z<r.z;
}
};
int n, m, k;
unordered_set<ll> st;
Edge edge[500002];
int ex[22], ey[22];
int root;
ll arr[100002];
ll ans;
vector<pair<int, ll> > rLink[100002];
vector<pair<int, int> > nLink[100002];
void input(){
scanf("%d %d %d", &n, &m, &k);
for(int i=1; i<=m; i++){
int x, y, z;
scanf("%d %d %d", &x, &y, &z);
edge[i] = Edge(x, y, z);
}
sort(edge+1, edge+m+1);
for(int i=0; i<k; i++){
scanf("%d %d", &ex[i], &ey[i]);
}
for(int i=1; i<=n; i++) scanf("%lld", &arr[i]);
}
vector<int> specialVec (1, -1);
int indices[100002];
int group[100002];
ll minWeight[42][42];
void contractGraph(){
dsu.init(n);
dsu2.init(n);
for(int i=0; i<k; i++){
dsu.merge(ex[i], ey[i]);
specialVec.push_back(ex[i]);
specialVec.push_back(ey[i]);
}
sort(specialVec.begin(), specialVec.end());
specialVec.erase(unique(specialVec.begin(), specialVec.end()), specialVec.end());
for(int i=1; i<(int)specialVec.size(); i++) indices[specialVec[i]] = i;
for(int i=1; i<=m; i++){
Edge e = edge[i];
if(dsu.find(e.x) == dsu.find(e.y)) continue;
dsu.merge(e.x, e.y);
dsu2.merge(e.x, e.y);
}
for(int i=1; i<=n; i++){
for(int j=1; j<(int)specialVec.size(); j++){
if(dsu2.find(i) == dsu2.find(specialVec[j])){
group[i] = j;
break;
}
}
assert(group[i]);
}
root = group[1];
vector<ll> tarr (arr, arr+n+1);
memset(arr, 0, sizeof(arr));
for(int i=1; i<=n; i++) arr[group[i]] += tarr[i];
n = (int)specialVec.size()-1;
assert(n<=k*2);
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) minWeight[i][j] = 1e18;
vector<Edge> edgeVec;
for(int i=1; i<=m; i++){
edge[i].x = group[edge[i].x], edge[i].y = group[edge[i].y];
if(edge[i].x == edge[i].y) continue;
if(edge[i].x > edge[i].y) swap(edge[i].x, edge[i].y);
minWeight[edge[i].x][edge[i].y] = min(minWeight[edge[i].x][edge[i].y], edge[i].z);
// edgeVec.push_back(Edge(edge[i].x, edge[i].y, edge[i].z));
}
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
if(minWeight[i][j] > 1e17) continue;
edgeVec.push_back(Edge(i, j, minWeight[i][j]));
}
sort(edgeVec.begin(), edgeVec.end());
m = (int)edgeVec.size();
for(int i=1; i<=m; i++){
edge[i] = edgeVec[i-1];
}
for(int i=0; i<k; i++){
ex[i] = group[ex[i]], ey[i] = group[ey[i]];
assert(ex[i] != ey[i]);
st.insert(ll(ex[i])*1000000+ey[i]);
st.insert(ll(ey[i])*1000000+ex[i]);
}
}
ll calc(int x, int p=-1, ll sum=0){
ll ret = arr[x] * sum;
for(auto y: rLink[x]){
if(y.first == p) continue;
ret += calc(y.first, x, sum + ((st.find(ll(x)*1000000+y.first) != st.end()) ? y.second : 0));
}
return ret;
}
bool dfs(int x, int p, int goal, vector<int> &vec){
if(x==goal) return true;
for(auto y: nLink[x]){
if(y.first == p) continue;
vec.push_back(y.second);
if(dfs(y.first, x, goal, vec)) return true;
vec.pop_back();
}
for(auto y: rLink[x]){
if(y.first == p) continue;
if(dfs(y.first, x, goal, vec)) return true;
}
return false;
}
int main(){
input();
contractGraph();
for(int b=1; b<(1<<k); b++){ /// b: 선택된 추가 간선들의 집합
/// cycle detection
dsu2.init(n);
bool bad = 0;
for(int i=1; i<=n; i++) nLink[i].clear();
for(int i=0; i<k; i++){
if((b&(1<<i))==0) continue;
if(dsu2.find(ex[i]) == dsu2.find(ey[i])){
bad = 1;
break;
}
dsu2.merge(ex[i], ey[i]);
nLink[ex[i]].push_back(make_pair(ey[i], i));
nLink[ey[i]].push_back(make_pair(ex[i], i));
}
if(bad) continue;
dsu.init(n);
for(int i=1; i<=n; i++) rLink[i].clear();
for(int pnt=1; pnt<=m; pnt++){ /// 가장 가중치 작은 edge부터 시도해 보기
Edge e = edge[pnt];
if(dsu.find(e.x) == dsu.find(e.y)) continue;
ll w = e.z;
if(dsu2.find(e.x) != dsu2.find(e.y)){ /// 추가해도 되는 경우
rLink[e.x].push_back(make_pair(e.y, w));
rLink[e.y].push_back(make_pair(e.x, w));
dsu.merge(e.x, e.y);
dsu2.merge(e.x, e.y);
}
else{ /// 추가하면 안되는 경우
vector<int> delVec;
dfs(e.x, -1, e.y, delVec);
for(auto x: delVec){
nLink[ex[x]].erase(find(nLink[ex[x]].begin(), nLink[ex[x]].end(), make_pair(ey[x], x)));
nLink[ey[x]].erase(find(nLink[ey[x]].begin(), nLink[ey[x]].end(), make_pair(ex[x], x)));
rLink[ex[x]].push_back(make_pair(ey[x], w));
rLink[ey[x]].push_back(make_pair(ex[x], w));
dsu.merge(ex[x], ey[x]);
}
}
}
ans = max(ans, calc(root));
}
printf("%lld", ans);
}
Compilation message (stderr)
toll.cpp: In function 'void input()':
toll.cpp:47:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
47 | scanf("%d %d %d", &n, &m, &k);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
toll.cpp:50:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
50 | scanf("%d %d %d", &x, &y, &z);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
toll.cpp:55:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
55 | scanf("%d %d", &ex[i], &ey[i]);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
toll.cpp:57:34: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
57 | for(int i=1; i<=n; i++) scanf("%lld", &arr[i]);
| ~~~~~^~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |