Problem:
C: 橋作り
問題
\(N\) 個の島と \(M\) 個の橋の建造計画があります。
\(i\) 番目の計画は \(u_i\) 番目の島と \(v_i\) 番目の島を結ぶ橋を作るもので、定数 \(a_i,b_i\) と建造開始を1日目としたときの日にちによって利益が決まります。
ととりにゃあは1日に以下の2つの行動のうちいずれかを1回行うことができます。
まだ建造されていない \(i\) 番目の橋の建造を行います。それが \(D\) 日目の場合 \(a_iD+b_i\) の利益を得ます。
橋の建造を終えます。ただし、全ての島が連結になっている必要があります。
ととりにゃあが得られる利益の最大値を求めてください。
入力形式
N
M
u_1
v_1
a_1
b_1
u_2
v_2
a_2
b_2
︙
u_M
v_M
a_M
b_M
制約
\(2 \leq N \leq 2\times 10^5\)
\(N-1 \leq M \leq \mathrm{min}(\frac{N(N-1)}{2} , N ) \)
\(1 \leq u_i \lt v_i \leq N\)
\(i \neq j\) ならば \((u_i,v_i) \neq (u_j,v_j) \)
\(|a_i|,|b_i| \leq 10^5\)
全ての橋を建設すると、全ての島は連結になる
入力は全て整数である
出力形式
ととりにゃあが得られる利益の最大値を出力してください。
入力例1
3 3
1 2 1 -10
1 3 3 1
2 3 2 2
出力例1
11
以下のように行動すると、11の利益を得ることができます。
\(1\) 日目: 橋\(3\) の建造をして、\(2\times1+2=4\) の利益を得る。
\(2\) 日目: 橋\(2\) の建造をして、\(3\times2+1=7\) の利益を得る。
\(3\) 日目: 橋の建造をやめる。
入力例2
5 4
2 4 -52 -52
2 3 14 -11
4 5 -2 -54
1 3 46 8
出力例2
61
入力例3
7 7
4 7 51373 53199
1 5 -47225 -49093
6 7 -23113 -65826
2 4 43632 -51039
4 5 32479 -17794
3 4 -76774 92308
1 6 -67028 23587
出力例3
410580

Submitted solutions:

code_snippet: #include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <numeric>
#include <algorithm>
#include <queue>
#include <string>
#include <random>
#include <array>


class UnionFind {
	std::vector<int> vec;
public:
	UnionFind(const int size) : vec(size, -1) {};
	int find(const int a) {
		if (vec[a] < 0) return a;
		return vec[a] = find(vec[a]);
	}
	void unite(int a, int b) {
		a = find(a);
		b = find(b);
		if (a == b) return;
		if (vec[a] > vec[b]) std::swap(a, b);
		vec[a] += vec[b];
		vec[b] = a;
	}
	bool same(const int a, const int b) {
		return find(a) == find(b);
	}
};
long long int solve(const int n, const int m, std::vector<std::array<int, 4>> bridges) {
	std::sort(bridges.begin(), bridges.end(), [](const auto& a, const auto& b) {return a[2] < b[2]; });

	long long int initial{ 0 };
	for (auto i = 0; i < m; ++i) {
		const auto a = bridges[i][2];
		const auto b = bridges[i][3];
		initial += a * (i + 1LL) + b;
	}
	if (m == n - 1) {
		return initial;
	}
	UnionFind uft(n);
	int cycle_edge{ -1 };
	std::vector<std::vector<std::pair<int, int>>> graph(n);
	for (auto i = 0; i < m; ++i) {
		const auto [u, v, a, b] = bridges[i];
		if (uft.same(u, v)) {
			cycle_edge = i;
		}
		else {
			uft.unite(u, v);
			graph[u].emplace_back(i, v);
			graph[v].emplace_back(i, u);
		}
	}
	std::vector<int> depth(n, -1); depth[0] = 0;
	std::vector<std::pair<int, int>> parent_edge(n);
	std::queue<int> queue; queue.push(0);
	while (!queue.empty()) {
		const auto current = queue.front(); queue.pop();
		for (const auto &[i, next]: graph[current]) {
			if (depth[next] >= 0) continue;
			parent_edge[next] = std::make_pair(i, current);
			depth[next] = depth[current] + 1;
			queue.push(next);
		}
	}
	std::vector<int> removable{cycle_edge};
	{
		const auto u = bridges[cycle_edge][0];
		const auto v = bridges[cycle_edge][1];
		auto current_u = u;
		auto current_v = v;
		while (depth[current_v] < depth[current_u]) {
			const auto [i, p] = parent_edge[current_u];
			removable.push_back(i);
			current_u = p;
		}
		while (depth[current_u] < depth[current_v]) {
			const auto [i, p] = parent_edge[current_v];
			removable.push_back(i);
			current_v = p;
		}
		while (current_u != current_v) {
			const auto [ui, up] = parent_edge[current_u];
			const auto [vi, vp] = parent_edge[current_v];
			removable.push_back(ui);
			removable.push_back(vi);
			current_u = up;
			current_v = vp;
		}
	}
	std::vector<long long int> a_sum{ 0 };
	long long int b_sum{ 0 };
	for (const auto &[u, v, a, b]: bridges) {
		a_sum.push_back(a_sum.back() + a);
		b_sum += b;
	}
	long long int result = initial;
	for (const auto e : removable) {
		const auto right_a = a_sum.back() - a_sum[e] - bridges[e][2];
		const auto value = initial - right_a - (e + 1LL) * bridges[e][2] - bridges[e][3];
		result = std::max(result, value);
	}
	return result;
}
int main() {
	int n, m; std::cin >> n >> m;
	std::vector<std::array<int, 4>> bridges(m, std::array<int, 4>());
	for (auto& [u, v, a, b] : bridges) {
		std::cin >> u >> v >> a >> b;
		--u; --v;
	}
	const auto result = solve(n, m, bridges);
	std::cout << result << '\n';
}
accuracy: 1
time_ms: 180
memory_kb: 28780
final_rank: 3

code_snippet: #include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <numeric>
#include <algorithm>
#include <queue>
#include <string>
#include <random>
#include <array>


class UnionFind {
	std::vector<int> vec;
public:
	UnionFind(const int size) : vec(size, -1) {};
	int find(const int a) {
		if (vec[a] < 0) return a;
		return vec[a] = find(vec[a]);
	}
	void unite(int a, int b) {
		a = find(a);
		b = find(b);
		if (a == b) return;
		if (vec[a] > vec[b]) std::swap(a, b);
		vec[a] += vec[b];
		vec[b] = a;
	}
	bool same(const int a, const int b) {
		return find(a) == find(b);
	}
};
long long int solve(const int n, const int m, std::vector<std::array<int, 4>> bridges) {
	std::sort(bridges.begin(), bridges.end(), [](const auto& a, const auto& b) {return a[2] < b[2]; });

	long long int initial{ 0 };
	for (auto i = 0; i < m; ++i) {
		const auto a = bridges[i][2];
		const auto b = bridges[i][3];
		initial += a * (i + 1) + b;
	}
	if (m == n - 1) {
		return initial;
	}
	UnionFind uft(n);
	int cycle_edge{ -1 };
	std::vector<std::vector<std::pair<int, int>>> graph(n);
	for (auto i = 0; i < m; ++i) {
		const auto [u, v, a, b] = bridges[i];
		if (uft.same(u, v)) {
			cycle_edge = i;
		}
		else {
			uft.unite(u, v);
			graph[u].emplace_back(i, v);
			graph[v].emplace_back(i, u);
		}
	}
	std::vector<int> depth(n, -1); depth[0] = 0;
	std::vector<std::pair<int, int>> parent_edge(n);
	std::queue<int> queue; queue.push(0);
	while (!queue.empty()) {
		const auto current = queue.front(); queue.pop();
		for (const auto &[i, next]: graph[current]) {
			if (depth[next] >= 0) continue;
			parent_edge[next] = std::make_pair(i, current);
			depth[next] = depth[current] + 1;
			queue.push(next);
		}
	}
	std::vector<int> removable{cycle_edge};
	{
		const auto u = bridges[cycle_edge][0];
		const auto v = bridges[cycle_edge][1];
		auto current_u = u;
		auto current_v = v;
		while (depth[current_v] < depth[current_u]) {
			const auto [i, p] = parent_edge[current_u];
			removable.push_back(i);
			current_u = p;
		}
		while (depth[current_u] < depth[current_v]) {
			const auto [i, p] = parent_edge[current_v];
			removable.push_back(i);
			current_v = p;
		}
		while (current_u != current_v) {
			const auto [ui, up] = parent_edge[current_u];
			const auto [vi, vp] = parent_edge[current_v];
			removable.push_back(ui);
			removable.push_back(vi);
			current_u = up;
			current_v = vp;
		}
	}
	std::vector<long long int> a_sum{ 0 };
	long long int b_sum{ 0 };
	for (const auto &[u, v, a, b]: bridges) {
		a_sum.push_back(a_sum.back() + a);
		b_sum += b;
	}
	long long int result = initial;
	for (const auto e : removable) {
		const auto right_a = a_sum.back() - a_sum[e] - bridges[e][2];
		const auto value = initial - right_a - (e + 1) * bridges[e][2] - bridges[e][3];
		result = std::max(result, value);
	}
	return result;
}
int main() {
	int n, m; std::cin >> n >> m;
	std::vector<std::array<int, 4>> bridges(m, std::array<int, 4>());
	for (auto& [u, v, a, b] : bridges) {
		std::cin >> u >> v >> a >> b;
		--u; --v;
	}
	const auto result = solve(n, m, bridges);
	std::cout << result << '\n';
}
accuracy: 0.1111111111111111
time_ms: 130
memory_kb: 9216
final_rank: 20

code_snippet: #include<bits/stdc++.h> 
using namespace std;
template<typename T1,typename T2> bool chmax(T1 &a,T2 b){if(a>=b)return 0; a=b; return 1;}


int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(20);

    int N,M;
    cin>>N>>M;
    using pii=pair<int,int>;
    vector<int> a(M),b(M);
    vector<vector<int>> g(N);
    map<pii,int> id;
    for(int i=0;i<M;i++){
        int u,v;
        cin>>u>>v>>a[i]>>b[i];
        u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
        id[pii(u,v)]=i;
        id[pii(v,u)]=i;
    }
//橋の判別を開始
    vector<bool> bridge(M,false); //bridge[i]: i番目の辺は橋か
    queue<int> que; //次数が1の頂点を入れる
    vector<int> cnt(N,0); //i番目の頂点の次数
    for(int i=0;i<N;i++){
        for(int to:g[i]) cnt[to]++;
    }
    for(int i=0;i<N;i++){
        if(cnt[i]==1) que.push(i);
    }
    while(que.size()){
        int x=que.front(); que.pop(); //x: 次数が1の頂点
        for(int to:g[x]){
            bridge[id[pii(x,to)]]=true; //次数が1の頂点から伸びている辺は橋
            cnt[to]--; //xからでている辺を取り除く
            if(cnt[to]==1) que.push(to); //次数が1の頂点をqueに入れる
        }

    }
//橋の判別を終了

    vector<int> order(M);
    for(int i=0;i<M;i++) order[i]=i;

    sort(order.begin(),order.end(),
        [&](int i,int j){
            return a[i]<a[j];
        });
    long long int sum=0;

    for(long long int i=0;i<M;i++){
        int x=order[i];
        sum+=a[x]*(i+1)+b[x];
    }
    long long int ans=sum; //全ての橋を建造した場合の最適解
    if(M==N-1){
        cout<<ans<<endl;
        return 0;
    }
    vector<long long int> suma(M); //aの累積和

    for(int i=0;i<M;i++){
        int x=order[i];
        suma[i]=a[x];
        if(i) suma[i]+=suma[i-1];
    } 
    for(long long int i=0;i<M;i++){
        int x=order[i];
        if(not bridge[x]){
            chmax(ans,sum-a[x]*(i+1)-b[x]-(suma[M-1]-suma[i]) );
        }
    }
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 350
memory_kb: 45060
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define int ll
#define ALL(x) begin(x),end(x)
#define rep(i,n) for(int i=0;i<(n);i++)
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define mod 1000000007
using ll=long long;
const int INF=1000000000;
const ll LINF=1001002003004005006ll;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
// ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}

struct IOSetup{
    IOSetup(){
        cin.tie(0);
        ios::sync_with_stdio(0);
        cout<<fixed<<setprecision(12);
    }
} iosetup;

template<typename T>
ostream &operator<<(ostream &os,const vector<T>&v){
    for(int i=0;i<(int)v.size();i++) os<<v[i]<<(i+1==(int)v.size()?"":" ");
    return os;
}
template<typename T>
istream &operator>>(istream &is,vector<T>&v){
    for(T &x:v)is>>x;
    return is;
}

// graph template
// ref : https://ei1333.github.io/library/graph/graph-template.cpp
template<typename T=int>
struct Edge{
    int from,to;
    T w;
    int idx;
    Edge()=default;
    Edge(int from,int to,T w=1,int idx=-1):from(from),to(to),w(w),idx(idx){}
    operator int() const{return to;}
};

template<typename T=int>
struct Graph{
    vector<vector<Edge<T>>> g;
    int V,E;
    Graph()=default;
    Graph(int n):g(n),V(n),E(0){}

    int size(){
        return (int)g.size();
    }
    void resize(int k){
        g.resize(k);
        V=k;
    }
    inline const vector<Edge<T>> &operator[](int k)const{
        return (g.at(k));
    }
    inline vector<Edge<T>> &operator[](int k){
        return (g.at(k));
    }
    void add_directed_edge(int from,int to,T cost=1){
        g[from].emplace_back(from,to,cost,E++);
    }
    void add_edge(int from,int to,T cost=1){
        g[from].emplace_back(from,to,cost,E);
        g[to].emplace_back(to,from,cost,E++);
    }
    void read(int m,int pad=-1,bool weighted=false,bool directed=false){
        for(int i=0;i<m;i++){
            int u,v;cin>>u>>v;
            u+=pad,v+=pad;
            T w=T(1);
            if(weighted) cin>>w;
            if(directed) add_directed_edge(u,v,w);
            else         add_edge(u,v,w);
        }
    }
};

template<typename T>
vector<Edge<T>> enumerate_cycle_on_namori(Graph<T> G){
    queue<int> que;
    vector<int> deg(G.size());
    for(int i=0;i<G.size();i++){
        deg[i]=(int)G[i].size();
        if(deg[i]==1) que.push(i);
    }
    while(!que.empty()){
        int cur=que.front();que.pop();
        deg[cur]=-1;
        for(auto &e:G[cur]){
            deg[e]--;
            if(deg[e]==1) que.push(e);
        }   
    }

    vector<Edge<T>> ret;
    for(int i=0;i<G.size();i++){
        if(deg[i]>=0){
            for(auto &e:G[i])if(deg[e]>=0) ret.push_back(e);
        }
    }
    return ret;
}

using P=pair<ll,ll>;
using T=tuple<ll,ll,int>;

signed main(){
    int N,M;cin>>N>>M;
    Graph<P> G(N);
    vector<T> V;
    rep(i,M){
        int u,v;ll a,b;cin>>u>>v>>a>>b;
        u--,v--;
        G.add_edge(u,v,P(a,b));
        V.emplace_back(a,b,i);        
    }

    sort(ALL(V));

    ll res=0;
    rep(i,M) res+=get<0>(V[i])*(i+1)+get<1>(V[i]);
    if(M==N-1){
        cout<<res<<endl;
        return 0;
    }

    vector<ll> S(M+1,0);
    rep(i,M) S[i+1]=S[i]+get<0>(V[i]);
    vector<int> check(M,0);

    for(auto e:enumerate_cycle_on_namori(G)){
        check[e.idx]=true;
    }

    ll tot=res;
    rep(i,M){
        ll a,b;int idx;
        tie(a,b,idx)=V[i];
        if(check[idx]){
            chmax(res,tot-S[M]+S[i+1]-b-a*(i+1));
        }
    }
    cout<<res<<endl;
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 86484
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define int ll
#define ALL(x) begin(x),end(x)
#define rep(i,n) for(int i=0;i<(n);i++)
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define mod 1000000007
using ll=long long;
const int INF=1000000000;
const ll LINF=1001002003004005006ll;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
// ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}

struct IOSetup{
    IOSetup(){
        cin.tie(0);
        ios::sync_with_stdio(0);
        cout<<fixed<<setprecision(12);
    }
} iosetup;

template<typename T>
ostream &operator<<(ostream &os,const vector<T>&v){
    for(int i=0;i<(int)v.size();i++) os<<v[i]<<(i+1==(int)v.size()?"":" ");
    return os;
}
template<typename T>
istream &operator>>(istream &is,vector<T>&v){
    for(T &x:v)is>>x;
    return is;
}

// graph template
// ref : https://ei1333.github.io/library/graph/graph-template.cpp
template<typename T=int>
struct Edge{
    int from,to;
    T w;
    int idx;
    Edge()=default;
    Edge(int from,int to,T w=1,int idx=-1):from(from),to(to),w(w),idx(idx){}
    operator int() const{return to;}
};

template<typename T=int>
struct Graph{
    vector<vector<Edge<T>>> g;
    int V,E;
    Graph()=default;
    Graph(int n):g(n),V(n),E(0){}

    int size(){
        return (int)g.size();
    }
    void resize(int k){
        g.resize(k);
        V=k;
    }
    inline const vector<Edge<T>> &operator[](int k)const{
        return (g.at(k));
    }
    inline vector<Edge<T>> &operator[](int k){
        return (g.at(k));
    }
    void add_directed_edge(int from,int to,T cost=1){
        g[from].emplace_back(from,to,cost,E++);
    }
    void add_edge(int from,int to,T cost=1){
        g[from].emplace_back(from,to,cost,E);
        g[to].emplace_back(to,from,cost,E++);
    }
    void read(int m,int pad=-1,bool weighted=false,bool directed=false){
        for(int i=0;i<m;i++){
            int u,v;cin>>u>>v;
            u+=pad,v+=pad;
            T w=T(1);
            if(weighted) cin>>w;
            if(directed) add_directed_edge(u,v,w);
            else         add_edge(u,v,w);
        }
    }
};

template<typename T>
vector<Edge<T>> enumerate_cycle_on_namori(Graph<T> G){
    queue<int> que;
    vector<int> deg(G.size());
    for(int i=0;i<G.size();i++){
        deg[i]=(int)G[i].size();
        if(deg[i]==1) que.push(i);
    }
    while(!que.empty()){
        int cur=que.front();que.pop();
        deg[cur]=-1;
        for(auto &e:G[cur]){
            deg[e]--;
            if(deg[e]==1) que.push(e);
        }   
    }

    vector<Edge<T>> ret;
    for(int i=0;i<G.size();i++){
        if(deg[i]>=0){
            for(auto &e:G[i])if(deg[e]>=0) ret.push_back(e);
        }
    }
    return ret;
}

using P=pair<ll,ll>;
using T=tuple<ll,ll,int>;

signed main(){
    int N,M;cin>>N>>M;
    Graph<P> G(N);
    vector<T> V;
    rep(i,M){
        int u,v;ll a,b;cin>>u>>v>>a>>b;
        u--,v--;
        G.add_edge(u,v,P(a,b));
        V.emplace_back(a,b,i);        
    }

    sort(ALL(V));

    ll res=0;
    rep(i,M) res+=get<0>(V[i])*(i+1)+get<1>(V[i]);
    if(M==N-1){
        cout<<res<<endl;
        return 0;
    }

    vector<ll> S(M+1,0);
    rep(i,M) S[i+1]=S[i]+get<0>(V[i]);
    vector<int> check(M,0);

    for(auto e:enumerate_cycle_on_namori(G)){
        check[e.idx]=true;
    }

    ll tot=res;
    rep(i,M){
        ll a,b;int idx;
        tie(a,b,idx)=V[i];
        if(check[i]){
            chmax(res,tot-S[M]+S[i+1]-b-a*(i+1));
        }
    }
    cout<<res<<endl;
    return 0;
}
accuracy: 0.14814814814814814
time_ms: 140
memory_kb: 63684
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ALL(x) begin(x),end(x)
#define rep(i,n) for(int i=0;i<(n);i++)
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define mod 1000000007
using ll=long long;
const int INF=1000000000;
const ll LINF=1001002003004005006ll;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
// ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}

struct IOSetup{
    IOSetup(){
        cin.tie(0);
        ios::sync_with_stdio(0);
        cout<<fixed<<setprecision(12);
    }
} iosetup;

template<typename T>
ostream &operator<<(ostream &os,const vector<T>&v){
    for(int i=0;i<(int)v.size();i++) os<<v[i]<<(i+1==(int)v.size()?"":" ");
    return os;
}
template<typename T>
istream &operator>>(istream &is,vector<T>&v){
    for(T &x:v)is>>x;
    return is;
}

// graph template
// ref : https://ei1333.github.io/library/graph/graph-template.cpp
template<typename T=int>
struct Edge{
    int from,to;
    T w;
    int idx;
    Edge()=default;
    Edge(int from,int to,T w=1,int idx=-1):from(from),to(to),w(w),idx(idx){}
    operator int() const{return to;}
};

template<typename T=int>
struct Graph{
    vector<vector<Edge<T>>> g;
    int V,E;
    Graph()=default;
    Graph(int n):g(n),V(n),E(0){}

    int size(){
        return (int)g.size();
    }
    void resize(int k){
        g.resize(k);
        V=k;
    }
    inline const vector<Edge<T>> &operator[](int k)const{
        return (g.at(k));
    }
    inline vector<Edge<T>> &operator[](int k){
        return (g.at(k));
    }
    void add_directed_edge(int from,int to,T cost=1){
        g[from].emplace_back(from,to,cost,E++);
    }
    void add_edge(int from,int to,T cost=1){
        g[from].emplace_back(from,to,cost,E);
        g[to].emplace_back(to,from,cost,E++);
    }
    void read(int m,int pad=-1,bool weighted=false,bool directed=false){
        for(int i=0;i<m;i++){
            int u,v;cin>>u>>v;
            u+=pad,v+=pad;
            T w=T(1);
            if(weighted) cin>>w;
            if(directed) add_directed_edge(u,v,w);
            else         add_edge(u,v,w);
        }
    }
};

template<typename T>
vector<Edge<T>> enumerate_cycle_on_namori(Graph<T> G){
    queue<int> que;
    vector<int> deg(G.size());
    for(int i=0;i<G.size();i++){
        deg[i]=(int)G[i].size();
        if(deg[i]==1) que.push(i);
    }
    while(!que.empty()){
        int cur=que.front();que.pop();
        deg[cur]=-1;
        for(auto &e:G[cur]){
            deg[e]--;
            if(deg[e]==1) que.push(e);
        }   
    }

    vector<Edge<T>> ret;
    for(int i=0;i<G.size();i++){
        if(deg[i]>=0){
            for(auto &e:G[i])if(deg[e]>=0) ret.push_back(e);
        }
    }
    return ret;
}

using P=pair<ll,ll>;
using T=tuple<ll,ll,int>;

signed main(){
    int N,M;cin>>N>>M;
    Graph<P> G(N);
    vector<T> V;
    rep(i,M){
        int u,v;ll a,b;cin>>u>>v>>a>>b;
        u--,v--;
        G.add_edge(u,v,P(a,b));
        V.emplace_back(a,b,i);        
    }

    sort(ALL(V));

    ll res=0;
    rep(i,M) res+=get<0>(V[i])*(i+1)+get<1>(V[i]);
    if(M==N-1){
        cout<<res<<endl;
        return 0;
    }

    vector<ll> S(M+1,0);
    rep(i,M) S[i+1]=S[i]+get<0>(V[i]);
    vector<int> check(M,0);

    for(auto e:enumerate_cycle_on_namori(G)){
        check[e.idx]=true;
    }

    ll tot=res;
    rep(i,M){
        ll a,b;int idx;
        tie(a,b,idx)=V[i];
        if(check[i]){
            chmax(res,tot-S[M]+S[i+1]-b-a*(i+1));
        }
    }
    cout<<res<<endl;
    return 0;
}
accuracy: 0.14814814814814814
time_ms: 130
memory_kb: 56116
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(ll i=0;i<n;i++)
#define repl(i,l,r) for(ll i=(l);i<(r);i++)
#define per(i,n) for(ll i=(n)-1;i>=0;i--)
#define perl(i,r,l) for(ll i=r-1;i>=l;i--)
#define fi first
#define se second
#define pb push_back
#define ins insert
#define pqueue(x) priority_queue<x,vector<x>,greater<x>>
#define all(x) (x).begin(),(x).end()
#define CST(x) cout<<fixed<<setprecision(x)
#define vtpl(x,y,z) vector<tuple<x,y,z>>
#define rev(x) reverse(x);
using ll=long long;
using vl=vector<ll>;
using vvl=vector<vector<ll>>;
using pl=pair<ll,ll>;
using vpl=vector<pl>;
using vvpl=vector<vpl>;
const ll MOD=1000000007;
const ll MOD9=998244353;
const int inf=1e9+10;
const ll INF=4e18;
const ll dy[9]={0,1,-1,0,1,1,-1,-1,0};
const ll dx[9]={1,0,0,-1,1,-1,1,-1,0};
template<class T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
} 

struct UnionFind {
    vector<int> par;
    vector<int> edge;
    
    UnionFind(int n) : par(n, -1),edge(n, 0) {}

    int root(int x) {
        if (par[x] < 0) return x;
        else return par[x] = root(par[x]);
    }
    
    bool same(int x, int y) {
        return root(x) == root(y);
    }
    
    bool merge(int x, int y) {
        x = root(x); y = root(y);
        if (x == y) {
            edge[x]++;
            return false;
        }
        if (par[x] > par[y]) swap(x, y);
        par[x] += par[y];
        par[y] = x;
        edge[x] += edge[y]+1;
        return true;
    }
    
    int size(int x) {
        return -par[root(x)];
    }
};

struct edge{
    ll u,v,a,b;
    const bool operator<(const edge &e) const{
        return a<e.a;
    }
};
struct Edge {
    long long to;
};
using Graph = vector<vector<Edge>>;
struct LCA {
    vector<vector<int>> parent;  // parent[k][u]:= u の 2^k 先の親
    vector<int> dist;            // root からの距離
    LCA(const Graph &G, int root = 0) { init(G, root); }
    void init(const Graph &G, int root = 0) {
        int V = G.size();
        int K = 1;
        while ((1 << K) < V) K++;
        parent.assign(K, vector<int>(V, -1));
        dist.assign(V, -1);
        dfs(G, root, -1, 0);
        for (int k = 0; k + 1 < K; k++) {
            for (int v = 0; v < V; v++) {
                if (parent[k][v] >= 0) {
                    parent[k + 1][v] = parent[k][parent[k][v]];
                }
            }
        }
    }
    // 根からの距離と1つ先の頂点を求める
    void dfs(const Graph &G, int v, int p, int d) {
        parent[0][v] = p;
        dist[v] = d;
        for (auto e : G[v]) {
            if (e.to != p) {
                dfs(G, e.to, v, d + 1);
            }
        }
    }
    int query(int u, int v) {
        if (dist[u] < dist[v]) swap(u, v);  // u の方が深いとする
        int K = parent.size();
        // LCA までの距離を同じにする
        for (int k = 0; k < K; k++) {
            if ((dist[u] - dist[v])&(1<<k) ){
                u = parent[k][u];
            }
        }
        // 二分探索で LCA を求める
        if (u == v) return u;
        for (int k = K - 1; k >= 0; k--) {
            if (parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }
    int length(int u, int v) { return dist[u] + dist[v] - 2 * dist[query(u, v)]; }
    bool is_in(int u, int v, int a) { return length(u, a) + length(a, v) == length(u, v); }
};
int main(){
    ll n,m;cin >> n >> m;
    vector<edge> v(m);
    rep(i,m){
        ll s,t,a,b;cin >> s >> t >>  a >> b;s--;t--;
        v[i]={s,t,a,b};
    }
    sort(all(v));
    ll sum=0;
    rep(i,m){
        sum+=v[i].a*(i+1)+v[i].b;
    }
    if(m==n-1){
        cout << sum << endl;return 0;
    }
    UnionFind uf(n);
    edge es;
    vector<vector<Edge>> g(n);
    rep(i,m){
        if(uf.same(v[i].u,v[i].v)){
            es=v[i];
        }
        else{
            uf.merge(v[i].u,v[i].v);
            g[v[i].u].push_back({v[i].v});
            g[v[i].v].push_back({v[i].u});
        }
    }
    LCA lc(g);
    ll res=sum;
    vl cum(m);
    per(i,m-1)cum[i]+=cum[i+1]+v[i+1].a;
    //rep(i,m)cout << cum[i] << endl;
    rep(i,m){
        if(lc.is_in(es.u,es.v,v[i].u)&&lc.is_in(es.u,es.v,v[i].v)){
            ll ret=sum-cum[i]-v[i].a*(i+1)-v[i].b;
            chmax(res,ret);
            //cout << ret << endl;
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 430
memory_kb: 50200
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(ll i=0;i<n;i++)
#define repl(i,l,r) for(ll i=(l);i<(r);i++)
#define per(i,n) for(ll i=(n)-1;i>=0;i--)
#define perl(i,r,l) for(ll i=r-1;i>=l;i--)
#define fi first
#define se second
#define pb push_back
#define ins insert
#define pqueue(x) priority_queue<x,vector<x>,greater<x>>
#define all(x) (x).begin(),(x).end()
#define CST(x) cout<<fixed<<setprecision(x)
#define vtpl(x,y,z) vector<tuple<x,y,z>>
#define rev(x) reverse(x);
using ll=long long;
using vl=vector<ll>;
using vvl=vector<vector<ll>>;
using pl=pair<ll,ll>;
using vpl=vector<pl>;
using vvpl=vector<vpl>;
const ll MOD=1000000007;
const ll MOD9=998244353;
const int inf=1e9+10;
const ll INF=4e18;
const ll dy[9]={0,1,-1,0,1,1,-1,-1,0};
const ll dx[9]={1,0,0,-1,1,-1,1,-1,0};
template<class T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
} 

struct UnionFind {
    vector<int> par;
    vector<int> edge;
    
    UnionFind(int n) : par(n, -1),edge(n, 0) {}

    int root(int x) {
        if (par[x] < 0) return x;
        else return par[x] = root(par[x]);
    }
    
    bool same(int x, int y) {
        return root(x) == root(y);
    }
    
    bool merge(int x, int y) {
        x = root(x); y = root(y);
        if (x == y) {
            edge[x]++;
            return false;
        }
        if (par[x] > par[y]) swap(x, y);
        par[x] += par[y];
        par[y] = x;
        edge[x] += edge[y]+1;
        return true;
    }
    
    int size(int x) {
        return -par[root(x)];
    }
};

struct edge{
    ll u,v,a,b;
    const bool operator<(const edge &e) const{
        return a<e.a;
    }
};
struct Edge {
    long long to;
};
using Graph = vector<vector<Edge>>;
struct LCA {
    vector<vector<int>> parent;  // parent[k][u]:= u の 2^k 先の親
    vector<int> dist;            // root からの距離
    LCA(const Graph &G, int root = 0) { init(G, root); }
    void init(const Graph &G, int root = 0) {
        int V = G.size();
        int K = 1;
        while ((1 << K) < V) K++;
        parent.assign(K, vector<int>(V, -1));
        dist.assign(V, -1);
        dfs(G, root, -1, 0);
        for (int k = 0; k + 1 < K; k++) {
            for (int v = 0; v < V; v++) {
                if (parent[k][v] >= 0) {
                    parent[k + 1][v] = parent[k][parent[k][v]];
                }
            }
        }
    }
    // 根からの距離と1つ先の頂点を求める
    void dfs(const Graph &G, int v, int p, int d) {
        parent[0][v] = p;
        dist[v] = d;
        for (auto e : G[v]) {
            if (e.to != p) {
                dfs(G, e.to, v, d + 1);
            }
        }
    }
    int query(int u, int v) {
        if (dist[u] < dist[v]) swap(u, v);  // u の方が深いとする
        int K = parent.size();
        // LCA までの距離を同じにする
        for (int k = 0; k < K; k++) {
            if ((dist[u] - dist[v])&(1<<k) ){
                u = parent[k][u];
            }
        }
        // 二分探索で LCA を求める
        if (u == v) return u;
        for (int k = K - 1; k >= 0; k--) {
            if (parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }
    int length(int u, int v) { return dist[u] + dist[v] - 2 * dist[query(u, v)]; }
    bool is_in(int u, int v, int a) { return length(u, a) + length(a, v) == length(u, v); }
};
int main(){
    ll n,m;cin >> n >> m;
    vector<edge> v(m);
    rep(i,m){
        ll s,t,a,b;cin >> s >> t >>  a >> b;s--;t--;
        v[i]={s,t,a,b};
    }
    sort(all(v));
    ll sum=0;
    rep(i,m){
        sum+=v[i].a*(i+1)+v[i].b;
    }
    if(m==n-1){
        cout << sum << endl;return 0;
    }
    UnionFind uf(n);
    edge es;
    vector<vector<Edge>> g(n);
    rep(i,m){
        if(uf.same(v[i].u,v[i].v)){
            es=v[i];
        }
        else{
            uf.merge(v[i].u,v[i].v);
            g[v[i].u].push_back({v[i].v});
            g[v[i].v].push_back({v[i].u});
        }
    }
    LCA lc(g);
    ll res=-INF;
    vl cum(m);
    per(i,m-1)cum[i]+=cum[i+1]+v[i+1].a;
    //rep(i,m)cout << cum[i] << endl;
    rep(i,m){
        if(lc.is_in(es.u,es.v,v[i].u)&&lc.is_in(es.u,es.v,v[i].v)){
            ll ret=sum-cum[i]-v[i].a*(i+1)-v[i].b;
            chmax(res,ret);
        }
    }
    cout << res << endl;
}
accuracy: 0.7407407407407407
time_ms: 420
memory_kb: 50180
final_rank: 14

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;

int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    
    int N,M; cin >> N >> M;
    vector<pair<pair<int,int>,pair<int,int>>> edges;
    vector<vector<int>> G(N);
    rep(i,M){
        int u,v,a,b; cin >> u >> v >> a >> b;
        u--; v--;
        edges.push_back({{u, v}, {a, b}});
        G[u].push_back(v);
        G[v].push_back(u);
    }

    sort(edges.begin(), edges.end(), [&](pair<pair<int,int>,pair<int,int>> a, pair<pair<int,int>,pair<int,int>> b) {
        return a.second.first < b.second.first;
    });

    vector<int> used(N, 0), ord(N, 0), low(N, 0);
    set<pair<int,int>> bridges;
    function<int(int,int,int)> dfs = [&](int v, int k, int p) {
        used[v] = true;
        ord[v] = k++;
        low[v] = ord[v];
        int cnt = 0;
        for(int to : G[v]) {
            if(!used[to]) {
                cnt++;
                k = dfs(to, k, v);
                low[v] = min(low[v], low[to]);
                if(ord[v] < low[to]) bridges.insert({minmax(v, to)});
            } else if(to != p) {
                low[v] = min(low[v], ord[to]);
            }
        }
        return k;
    }; dfs(0, 0, -1);

    ll ALL = 0;
    rep(i,M){
        ll a = edges[i].second.first;
        ll b = edges[i].second.second;
        ll D = i + 1;
        ALL += a * D + b;
    }

    if(M == N - 1){ // tree
        cout << ALL << endl; return 0;
    }

    ll ans = ALL;
    vector<ll> sum(M + 1, 0);
    rep(i,M) sum[i + 1] += sum[i] + edges[i].second.first;
    rep(i,M) {
        int u,v; tie(u,v) = edges[i].first;
        if(!bridges.count({minmax(u, v)})) {
            ll a = edges[i].second.first;
            ll b = edges[i].second.second;
            ll D = i + 1;
            ans = max(ans, ALL - (a * D + b) - (sum[M] - sum[i + 1]));
        }
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 180
memory_kb: 50476
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(n);i++)
#define RREP(i,n) for(int i=(n-1);i>=0;i--)
#define ALL(v) v.begin(),v.end()

using ll=long long;
template< typename G >
struct Namori
{
  const G &g;
  vector< int > in;

  Namori(const G &g) : g(g), in(g.size(), 0) {}

  void decomposition(vector< int > &loop, vector< vector< int > > &forest)
  {
    int N = (int) in.size();
    for(int i = 0; i < N; i++) {
      in[i] = g[i].size();
    }
    forest.resize(N);
    queue< int > que;
    vector< bool > v(N, 0);
    for(int i = 0; i < N; i++) {
      if(in[i] == 1) {
        que.emplace(i);
        v[i] = true;
      }
    }
    while(!que.empty()) {
      int idx = que.front();
      que.pop();
      for(auto &to : g[idx]) {
        if(v[to]) continue;
        --in[to];
        forest[to].push_back(idx);
        forest[idx].push_back(to);
        if(in[to] > 1) continue;
        que.emplace(to);
        v[to] = true;
      }
    }

    function< void(int) > dfs = [&](int idx)
    {
      loop.push_back(idx);
      for(auto &to : g[idx]) {
        if(v[to]) continue;
        v[to] = true;
        dfs(to);
      }
    };
    for(int i = 0; i < N; i++) {
      if(v[i]) continue;
      v[i] = true;
      dfs(i);
      break;
    }
  }
};

int main(){
  int n,m;cin>>n>>m;
  vector<tuple<ll,ll,int,int>> w(m);
  vector<vector<int>> g(n);
  REP(i,m){
    int u,v,a,b;cin>>u>>v>>a>>b;u--;v--;
    w[i]={a,b,u,v};
    g[u].push_back(v);
    g[v].push_back(u);
  }
  sort(ALL(w));

  Namori<vector<vector<int>>> G(g);
  vector<int> loop;
  vector<vector<int>>forest;
  G.decomposition(loop,forest);

  ll sum=0;
  vector<ll> wa(m+1,0);
  REP(i,m){
    auto [a,b,u,v]=w[i];
    sum+=a*(i+1)+b;
    wa[i+1]=wa[i]+a;
  }
  ll ans=sum;

  if(m==n-1){
    cout<<ans<<endl;
    return 0;
  }

  set<tuple<int,int>> se;
  REP(i,loop.size()){
    int a=loop[i],b=loop[(i+1)%loop.size()];
    se.insert({min(a,b),max(a,b)});
  }
  
  REP(i,m){
    auto [a,b,u,v]=w[i];
    if(!se.count({u,v}))continue;
    ans=max(ans,sum-(a*(i+1)+b)-(wa[m]-wa[i+1]));
  }
  cout<<ans<<endl;
}
accuracy: 1
time_ms: 250
memory_kb: 45300
final_rank: 7

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#include <complex>
#include <unordered_set>
#include <unordered_map>
#define rep(x, s, t) for(ll x = (s); (x) <= (t); (x)++)
#define per(x, s, t) for(ll x = (s); (x) >= (t); (x)--)
#define reps(x, s) for(ll x = 0; (x) < (ll)(s).size(); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))
#define sz(x) ((ll)(x).size())
#define all(x) (x).begin(),(x).end()
#define outl(...) dump_func(__VA_ARGS__)
#define outf(x) cout << fixed << setprecision(16) << (x) << endl
#define inf 2e18
#define eps 1e-9
const double PI = 3.1415926535897932384626433;

using namespace std;

typedef long long llint;
typedef long long ll;
typedef pair<ll, ll> P;

struct edge{
	ll to, cost;
	edge(){}
	edge(ll a, ll b){ to = a, cost = b;}
};
const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};

//int mod = 1000000007;
int mod = 998244353;

struct mint{
	int x;
	mint(ll y = 0){if(y < 0 || y >= mod) y = (y%mod+mod)%mod; x = y;}
	mint(const mint &ope) {x = ope.x;}
	
	mint operator-(){return mint(-x);}
	mint operator+(const mint &ope){return mint(x) += ope;}
	mint operator-(const mint &ope){return mint(x) -= ope;}
	mint operator*(const mint &ope){return mint(x) *= ope;}
	mint operator/(const mint &ope){return mint(x) /= ope;}
	mint& operator+=(const mint &ope){
		x += ope.x;
		if(x >= mod) x -= mod;
		return *this;
	}
	mint& operator-=(const mint &ope){
		x += mod - ope.x;
		if(x >= mod) x -= mod;
		return *this;
	}
	mint& operator*=(const mint &ope){
		ll tmp = x;
		tmp *= ope.x, tmp %= mod;
		x = tmp;
		return *this;
	}
	mint& operator/=(const mint &ope){
		ll n = mod-2; mint mul = ope;
		while(n){
			if(n & 1) *this *= mul;
			mul *= mul;
			n >>= 1;
		}
		return *this;
	}
	mint inverse(){return mint(1) / *this;}
	bool operator ==(const mint &ope){return x == ope.x;}
	bool operator !=(const mint &ope){return x != ope.x;}
	bool operator <(const mint &ope){return x < ope.x;}
};
mint modpow(mint a, ll n){
	if(n == 0) return mint(1);
	if(n % 2) return a * modpow(a, n-1);
	else return modpow(a*a, n/2);
}
istream& operator >>(istream &is, mint &ope){
	ll t; is >> t, ope.x = t;
	return is;
}
ostream& operator <<(ostream &os, mint &ope){return os << ope.x;}
ostream& operator <<(ostream &os, const mint &ope){return os << ope.x;}

vector<mint> fact, fact_inv;
void make_fact(int n){
	fact.resize(n+1), fact_inv.resize(n+1);
	fact[0] = mint(1); rep(i, 1, n) fact[i] = fact[i-1] * mint(i);
	fact_inv[n] = fact[n].inverse(); per(i, n-1, 0) fact_inv[i] = fact_inv[i+1] * mint(i+1);
}
mint comb(int n, int k){ if(n < 0 || k < 0 || n < k) return mint(0); return fact[n] * fact_inv[k] * fact_inv[n-k];}
mint perm(int n, int k){ return comb(n, k) * fact[k]; }

vector<int> prime, pvec;
void make_prime(int n){
	prime.resize(n+1);
	rep(i, 2, n){
		if(prime[i]) continue;
		for(int j = i; j <= n; j+=i) prime[j] = i;
	}
	rep(i, 2, n) if(prime[i] == i) pvec.push_back(i);
}

bool exceed(ll x, ll y, ll m){return x >= m / y + 1;}
void mark(){ cout << "*" << endl; }
void yes(){ cout << "YES" << endl; }
void no(){ cout << "NO" << endl; }
ll floor(ll a, ll b){ if(b < 0) a *= -1, b *= -1; if(a >= 0) return a/b; else return -((-a+b-1)/b); }
ll ceil(ll a, ll b){ if(b < 0) a *= -1, b *= -1; if(a >= 0) return (a+b-1)/b; else return -((-a)/b); }
ll modulo(ll a, ll b){ b = abs(b); return a - floor(a, b) * b; }
ll sgn(ll x){ if(x > 0) return 1; if(x < 0) return -1; return 0;}
ll gcd(ll a, ll b){if(b == 0) return a; return gcd(b, a%b);}
ll lcm(ll a, ll b){return a/gcd(a, b)*b;}
ll digitnum(ll x, ll b = 10){ll ret = 0; for(; x; x /= b) ret++; return ret;}
ll digitsum(ll x, ll b = 10){ll ret = 0; for(; x; x /= b) ret += x % b; return ret;}
string lltos(ll x){string ret; for(;x;x/=10) ret += x % 10 + '0'; reverse(ret.begin(), ret.end()); return ret;}
ll stoll(string &s){ll ret = 0; for(auto c : s) ret *= 10, ret += c - '0'; return ret;}
template<typename T>
void uniq(T &vec){ sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end());}

template<class S, class T> pair<S, T>& operator+=(pair<S,T> &s, const pair<S,T> &t){
	s.first += t.first, s.second += t.second;
	return s;
}
template<class S, class T> pair<S, T>& operator-=(pair<S,T> &s, const pair<S,T> &t){
	s.first -= t.first, s.second -= t.second;
	return s;
}
template<class S, class T> pair<S, T> operator+(const pair<S,T> &s, const pair<S,T> &t){
	return pair<S,T>(s.first+t.first, s.second+t.second);
}
template<class S, class T> pair<S, T> operator-(const pair<S,T> &s, const pair<S,T> &t){
	return pair<S,T>(s.first-t.first, s.second-t.second);
}
template<typename T>
ostream& operator << (ostream& os, vector<T>& vec) {
	reps(i, vec) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os;
}
template<typename T>
ostream& operator << (ostream& os, const vector<T>& vec) {
	reps(i, vec) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os;
}
template<typename T>
ostream& operator << (ostream& os, deque<T>& deq) {
	reps(i,  deq) os << deq[i] << (i + 1 == deq.size() ? "" : " "); return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, pair<T, U>& pair_var) {
	os << "(" << pair_var.first << ", " << pair_var.second << ")";
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, const pair<T, U>& pair_var) {
	os << "(" << pair_var.first << ", " << pair_var.second << ")";
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, map<T, U>& map_var) {
	for(typename map<T, U>::iterator itr = map_var.begin(); itr != map_var.end(); itr++) {
		os << "(" << itr->first << ", " << itr->second << ")";
		itr++; if(itr != map_var.end()) os << ","; itr--;
	}
	return os;
}
template<typename T>
ostream& operator << (ostream& os, set<T>& set_var) {
	for(typename set<T>::iterator itr = set_var.begin(); itr != set_var.end(); itr++) {
		os << *itr; ++itr; if(itr != set_var.end()) os << " "; itr--;
	}
	return os;
}
template<typename T>
ostream& operator << (ostream& os, multiset<T>& set_var) {
	for(typename multiset<T>::iterator itr = set_var.begin(); itr != set_var.end(); itr++) {
		os << *itr; ++itr; if(itr != set_var.end()) os << " "; itr--;
	}
	return os;
}
template<typename T>
void outa(T a[], ll s, ll t){rep(i, s, t){ cout << a[i]; if(i < t) cout << " ";}cout << endl;}
void dump_func(){cout << endl;}
template <class Head, class... Tail>
void dump_func(Head &&head, Tail &&... tail) {
	cout << head;
	if(sizeof...(Tail) > 0) cout << " ";
	dump_func(std::move(tail)...);
}


struct DetectCycle{
	struct edge{
		int to, id;
		edge(){}
		edge(int a, int b){to = a, id = b;}
	};
	int n;
	vector<vector<edge> > G;
	vector<int> used;
	int eid;
	
	DetectCycle(){}
	DetectCycle(int n){init(n);}
	void init(int n){
		this->n = n;
		G.resize(n+1); for(int i = 0; i <= n; i++) G[i].clear();
		used.resize(n+1); for(int i = 0; i <= n; i++) used[i] = 0;
		eid = 0;
	}
	void add_edge(int u, int v){
		eid++;
		G[u].push_back(edge(v, eid));
		if(u != v) G[v].push_back(edge(u, eid));
	}
	int dfs(int v, int eid, vector<ll> &dest)
	{
		used[v] = 1;
		for(auto e : G[v]){
			int u = e.to, id = e.id;
			if(id == eid) continue;
			if(used[u]){
				dest.push_back(id);
				if(u == v) return -1;
				return u;
			}
			int res = dfs(u, id, dest);
			if(res == -1) return -1;
			if(res == -2) continue;
			dest.push_back(id);
			if(v == res) return -1;
			else return res;
		}
		return -2;
	}
	bool getCycle(int v, vector<ll> &dest){ //頂点vを含む連結成分のcycleの頂点を順番にdestに格納。戻り値はcycleの有無
		dest.clear();
		return dfs(v, -1, dest) == -1;
	}
};

typedef pair<P, ll> E;
ll n, m;
ll a[200005], b[200005];
E e[200005];
ll asum[200005];

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n >> m;
	DetectCycle dc(n);
	
	ll u, v;
	rep(i, 1, m){
		cin >> u >> v >> a[i] >> b[i];
		dc.add_edge(u, v);
	}
	vector<ll> cycle;
	dc.getCycle(1, cycle);
	
	rep(i, 1, m) e[i].first = P(a[i], b[i]);
	for(auto id : cycle) e[id].second = 1;
	sort(e+1, e+m+1);
	
	ll sum = 0;
	rep(i, 1, m){
		asum[i] = asum[i-1] + e[i].first.first;
		sum += i * e[i].first.first + e[i].first.second;
	}
	
	ll ans = sum;
	rep(i, 1, m){
		if(e[i].second) chmax(ans, sum-(asum[m]-asum[i])-(e[i].first.first*i+e[i].first.second));
	}
	outl(ans);
	
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 44540
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<int,P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 60;
// constexpr ll MOD = 1000000007;
constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-9;
const double PI = acos(-1);

#define ALL(v) (v).begin(),(v).end()
#define REP(i,n) for(int i=0,i_len=n; i<i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }

vector<vector<P> > g;
vector<int> ord, low;
vector<bool> is_articulation, is_bridge;
vector<int> bridges;

void dfs(int u, int par, int &k){
    ord[u] = k;
    k++;
    low[u] = ord[u];
    int cnt = 0;
    for(auto e : g[u]){
        int v = e.first;
        // dfsの子ノードへ移動
        if(ord[v] == -1){
            cnt++;
            dfs(v, u, k);
            low[u] = min(low[u], low[v]);
            if(par!=-1 && ord[u] <= low[v]){
                is_articulation[u] = true;
            }
            if(ord[u] < low[v]){
                is_bridge[e.second] = true;
            }
        }
        // dfs木の後退辺を移動
        else if(v != par)low[u] = min(low[u], ord[v]);
    }
    if(par == -1){
        is_articulation[u] = cnt >= 2;  // 根はdfs木の次数が2以上ならば関節点
    }
}

void lowlink(){
    ord.resize(g.size(), -1);
    low.resize(g.size());
    is_articulation.resize(g.size(), false);
    int k = 0;
    dfs(0, -1, k);
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    g.resize(n);
    vector<P> es(m);
    for(int i=0;i<m;i++){
        ll u, v, a, b;
        cin >> u >> v >> a >> b;
        u--; v--;
        g[u].push_back(P(v, i));
        g[v].push_back(P(u, i));
        es[i] = P(a,b);
    }
    vector<int> ord(m);
    iota(ALL(ord), 0);
    sort(ALL(ord), [&](const int& i, const int& j){return es[i].first < es[j].first;});
    vector<ll> cum(m+1);
    ll cost_all = 0, ans = 0;
    REP(i,m){
        auto [a,b] = es[ord[i]];
        cum[i+1] = cum[i] + es[ord[i]].first;
        cost_all += a*(i+1) + b;
    }
    ans = cost_all;
    is_bridge.resize(m, false);
    lowlink();
    for(int i=0;i<m;i++){
        if(!is_bridge[ord[i]]){
            auto [a,b] = es[ord[i]];
            chmax(ans, cost_all - (cum[m]-cum[i+1]) - (a*(i+1)+b));
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 47064
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<int,P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 60;
// constexpr ll MOD = 1000000007;
constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-9;
const double PI = acos(-1);

#define ALL(v) (v).begin(),(v).end()
#define REP(i,n) for(int i=0,i_len=n; i<i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }

vector<vector<P> > g;
vector<int> ord, low;
vector<bool> is_articulation, is_bridge;
vector<int> bridges;

void dfs(int u, int par, int &k){
    ord[u] = k;
    k++;
    low[u] = ord[u];
    int cnt = 0;
    for(auto e : g[u]){
        int v = e.first;
        // dfsの子ノードへ移動
        if(ord[v] == -1){
            cnt++;
            dfs(v, u, k);
            low[u] = min(low[u], low[v]);
            if(par!=-1 && ord[u] <= low[v]){
                is_articulation[u] = true;
            }
            if(ord[u] < low[v]){
                is_bridge[e.second] = true;
            }
        }
        // dfs木の後退辺を移動
        else if(v != par)low[u] = min(low[u], ord[v]);
    }
    if(par == -1){
        is_articulation[u] = cnt >= 2;  // 根はdfs木の次数が2以上ならば関節点
    }
}

void lowlink(){
    ord.resize(g.size(), -1);
    low.resize(g.size());
    is_articulation.resize(g.size(), false);
    int k = 0;
    dfs(0, -1, k);
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    g.resize(n);
    vector<P> es(m);
    for(int i=0;i<m;i++){
        int u, v, a, b;
        cin >> u >> v >> a >> b;
        u--; v--;
        g[u].push_back(P(v, i));
        g[v].push_back(P(u, i));
        es[i] = P(a,b);
    }
    vector<int> ord(m);
    iota(ALL(ord), 0);
    sort(ALL(es));
    vector<ll> cum(m+1);
    ll cost_all = 0, ans = 0;
    REP(i,m){
        auto [a,b] = es[ord[i]];
        cum[i+1] = cum[i] + es[ord[i]].first;
        cost_all += a*(i+1) + b;
    }
    ans = cost_all;
    is_bridge.resize(m, false);
    lowlink();
    for(int i=0;i<m;i++){
        if(!is_bridge[ord[i]]){
            auto [a,b] = es[ord[i]];
            chmax(ans, cost_all - (cum[m]-cum[i+1]) - (a*(i+1)+b));
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 0.14814814814814814
time_ms: 110
memory_kb: 43480
final_rank: 16

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int mod = 1e9 + 7;
//const int mod = 998244353;

int main(){
    int n,m; cin >> n >> m;
    vector<tapu> e(m);
    vector<set<P>> G(n);
    vb bridge(m,false);
    rep(i,m){
        int u,v,a,b; cin >> u >> v >> a >> b; u--; v--;
        G[u].emplace(v,i);
        G[v].emplace(u,i);
        e[i] = tie(a,b,i);
    }
    queue<int> q;
    rep(i,n) if(G[i].size() == 1) q.push(i);
    while(!q.empty()){
        int u = q.front(); q.pop();
        if(G[u].empty()) continue;
        int to = (*G[u].begin()).first;
        bridge[(*G[u].begin()).second] = true;
        auto itr = G[to].lower_bound(P(u,-inf));
        G[to].erase(itr);
        if(G[to].size() == 1) q.push(to);
    }
    sort(all(e));
    vl dp(2,-linf);
    dp[0] = 0;
    rep(i,m){
        vl ndp(2,-linf);
        ll a,b,id;
        tie(a,b,id) = e[i];
        rep(j,2) ndp[j] = dp[j] + a * (i+1-j) + b;
        if(!bridge[id]){
            chmax(ndp[1], dp[0]);
        }
        dp = ndp;
    }
    cout << max(dp[0],dp[1]) << endl;
}
accuracy: 1
time_ms: 250
memory_kb: 43128
final_rank: 6

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int mod = 1e9 + 7;
//const int mod = 998244353;

int main(){
    int n,m; cin >> n >> m;
    vector<tapu> e(m);
    vector<set<P>> G(n);
    vb bridge(m,false);
    rep(i,m){
        int u,v,a,b; cin >> u >> v >> a >> b; u--; v--;
        G[u].emplace(v,i);
        G[v].emplace(u,i);
        e[i] = tie(a,b,i);
    }
    queue<int> q;
    rep(i,n) if(G[i].size() == 1) q.push(i);
    while(!q.empty()){
        int u = q.front(); q.pop();
        int to = (*G[u].begin()).first;
        bridge[(*G[u].begin()).second] = true;
        auto itr = G[to].lower_bound(P(u,-inf));
        G[to].erase(itr);
        if(G[to].size() == 1) q.push(to);
    }
    sort(all(e));
    vl dp(2,-linf);
    dp[0] = 0;
    rep(i,m){
        vl ndp(2,-linf);
        ll a,b,id;
        tie(a,b,id) = e[i];
        rep(j,2) ndp[j] = dp[j] + a * (i+1-j) + b;
        if(!bridge[id]){
            chmax(ndp[1], dp[0]);
        }
        dp = ndp;
    }
    cout << max(dp[0],dp[1]) << endl;
}
accuracy: 0.4444444444444444
time_ms: 250
memory_kb: 43080
final_rank: 15

code_snippet: //#define _GLIBCXX_DEBUG

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};  
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge():id(-1){};
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
  Graph<T>ret(g.size());
  for(int i=0;i<g.size();i++){
    for(auto e:g[i]){
      int to = e.to;
      e.to = i;
      ret[to].push_back(e);
    }
  }
  return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v;
    T w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}
template<typename T>
struct Namori{
  const Graph<T>&g;
  int n;
  int edge_num=0;
  bool directed_forest = false;
  Namori(const Graph<T>&g, bool directed):g(g),n(g.size()){
    directed_forest = directed;
    int edge_num=0;
    for(auto &v:g)edge_num+=v.size();
    build();
  }
  vector<vector<int>>cycle;//連結成分の根となるサイクル サイクルではない場合も
  vector<vector<edge<T>>>cycle_edge;//辺属性
  vector<int>vn,en;//連結成分の頂点数、辺数
  Graph<T>forest;
  vector<int>root;
  vector<int>cycle_number;//頂点が属するサイクル番号 サイクルに属さなければ-1
  void build(){
    dfs_used.assign(n,false);
    dfs_now.assign(n,false);
    dfs_ver.clear();
    dfs_edge.clear();
    root.assign(n,-1);
    for(int i=0;i<n;i++){
      if(dfs_used[i])continue;
      cycle.emplace_back();
      cycle_edge.emplace_back();
      vn.push_back(0);
      en.push_back(0);
      build_dfs(i,-1,cycle.back(),cycle_edge.back());
      if(cycle.back().empty()){
        cycle.back().push_back(i);
      }
    }
    forest.resize(n);
    cycle_number.assign(n,-1);
    for(int i=0;i<cycle.size();i++){
      for(auto v:cycle[i])cycle_number[v]=i;
    }
    dfs_used.assign(n,false);
    for(int i=0;i<n;i++){
      if(cycle_number[i]!=-1)tree_dfs(i,vn[cycle_number[i]],en[cycle_number[i]],i);
    }
    for(int i=0;i<cycle.size();i++)en[i]>>=1;
  }
  void tree_dfs(int pos,int &vn,int &en,int r){
    vn++;
    dfs_used[pos]=true;
    root[pos]=r;
    for(auto e:g[pos]){
      en++;
      if(pos!=r&&dfs_used[e.to]&&!directed_forest)forest[pos].push_back(e);
      if(dfs_used[e.to]||cycle_number[e.to]!=-1)continue;
      forest[pos].push_back(e);
      tree_dfs(e.to,vn,en,r);
    }
  }
  vector<bool>dfs_used;
  vector<int>dfs_ver;
  vector<edge<T>>dfs_edge;
  vector<bool>dfs_now;
  void build_dfs(int pos, int par,vector<int>&cycle,vector<edge<T>>&cycle_edge){
    dfs_used[pos]=true;
    dfs_now[pos]=true;
    dfs_ver.push_back(pos);
    bool multiple_par=false;
    for(auto e:g[pos]){
      if(dfs_now[e.to]&&cycle.empty()&&(e.to!=par||multiple_par)){
        cycle_edge.PB(e);
        rep(i,0,dfs_ver.size()){
          if(!cycle.empty()||dfs_ver[i]==e.to)cycle.push_back(dfs_ver[i]);
          if(!cycle.empty())cycle_edge.push_back(dfs_edge[i]);
        }
        cycle_edge.pop_back();
      }
      if(e.to==par)multiple_par=true;
      if(dfs_used[e.to])continue;
      dfs_edge.push_back(e);
      build_dfs(e.to,pos,cycle,cycle_edge);
      dfs_edge.pop_back();
    }
    dfs_now[pos]=false;
    dfs_ver.pop_back();
  }
};
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  ll n,m;cin>>n>>m;
  Graph<P>g(n);
  vector<ll>u(m),v(m),a(m),b(m);
  rep(i,0,m){
    cin>>u[i]>>v[i]>>a[i]>>b[i];u[i]--;v[i]--;
    g[u[i]].EB(v[i],MP(a[i],b[i]),i);
    g[v[i]].EB(u[i],MP(a[i],b[i]),i);
  }
  auto ord=ascend(a);
  ll cnt=0;
  for(auto i:ord){
    res+=a[i]*(++cnt)+b[i];
  }
  if(m==n-1){
    cout<<res<<endl;
    return 0;
  }
  ll ret=res;
  Namori namori(g,true);
  vector<ll>pos(m);
  rep(i,0,m)pos[ord[i]]=i;
  vector<ll>ca(m+1);
  rep(i,0,m)ca[i+1]=ca[i]+a[ord[i]];
  //cout<<namori.vn[0] spa namori.en[0]<<endl;
  for(auto e:namori.cycle_edge[0]){
    //cout<<e.id<<" ";
    chmax(ret,res-(ca[m]-ca[pos[e.id]+1])-(a[e.id]*(pos[e.id]+1)+b[e.id]));
  }
  //cout<<endl;
  cout<<ret<<endl;
  return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 81108
final_rank: 10

code_snippet: //#define _GLIBCXX_DEBUG

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};  
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge():id(-1){};
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
  Graph<T>ret(g.size());
  for(int i=0;i<g.size();i++){
    for(auto e:g[i]){
      int to = e.to;
      e.to = i;
      ret[to].push_back(e);
    }
  }
  return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v;
    T w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}
template<typename T>
struct Namori{
  const Graph<T>&g;
  int n;
  int edge_num=0;
  bool directed_forest = false;
  Namori(const Graph<T>&g, bool directed):g(g),n(g.size()){
    directed_forest = directed;
    int edge_num=0;
    for(auto &v:g)edge_num+=v.size();
    build();
  }
  vector<vector<int>>cycle;//連結成分の根となるサイクル サイクルではない場合も
  vector<vector<edge<T>>>cycle_edge;//辺属性
  vector<int>vn,en;//連結成分の頂点数、辺数
  Graph<T>forest;
  vector<int>root;
  vector<int>cycle_number;//頂点が属するサイクル番号 サイクルに属さなければ-1
  void build(){
    dfs_used.assign(n,false);
    dfs_now.assign(n,false);
    dfs_ver.clear();
    dfs_edge.clear();
    root.assign(n,-1);
    for(int i=0;i<n;i++){
      if(dfs_used[i])continue;
      cycle.emplace_back();
      cycle_edge.emplace_back();
      vn.push_back(0);
      en.push_back(0);
      build_dfs(i,-1,cycle.back(),cycle_edge.back());
      if(cycle.back().empty()){
        cycle.back().push_back(i);
      }
    }
    forest.resize(n);
    cycle_number.assign(n,-1);
    for(int i=0;i<cycle.size();i++){
      for(auto v:cycle[i])cycle_number[v]=i;
    }
    dfs_used.assign(n,false);
    for(int i=0;i<n;i++){
      if(cycle_number[i]!=-1)tree_dfs(i,vn[cycle_number[i]],en[cycle_number[i]],i);
    }
    for(int i=0;i<cycle.size();i++)en[i]>>=1;
  }
  void tree_dfs(int pos,int &vn,int &en,int r){
    vn++;
    dfs_used[pos]=true;
    root[pos]=r;
    for(auto e:g[pos]){
      en++;
      if(pos!=r&&dfs_used[e.to]&&!directed_forest)forest[pos].push_back(e);
      if(dfs_used[e.to]||cycle_number[e.to]!=-1)continue;
      forest[pos].push_back(e);
      tree_dfs(e.to,vn,en,r);
    }
  }
  vector<bool>dfs_used;
  vector<int>dfs_ver;
  vector<edge<T>>dfs_edge;
  vector<bool>dfs_now;
  void build_dfs(int pos, int par,vector<int>&cycle,vector<edge<T>>&cycle_edge){
    dfs_used[pos]=true;
    dfs_now[pos]=true;
    dfs_ver.push_back(pos);
    bool multiple_par=false;
    for(auto e:g[pos]){
      if(dfs_now[e.to]&&cycle.empty()&&(e.to!=par||multiple_par)){
        for(auto v:dfs_ver){
          if(!cycle.empty()||v==e.to)cycle.push_back(v);
        }
        for(auto ee:dfs_edge){
          cycle_edge.push_back(ee);
        }
        cycle_edge.push_back(e);
      }
      if(e.to==par)multiple_par=true;
      if(dfs_used[e.to])continue;
      dfs_edge.push_back(e);
      build_dfs(e.to,pos,cycle,cycle_edge);
      dfs_edge.pop_back();
    }
    dfs_now[pos]=false;
    dfs_ver.pop_back();
  }
};
template<typename T>
vector<int>cycle_detection(const Graph<T>&g){
  int n=g.size();
  vector<int>ret;
  vector<int>v;
  vector<bool>used(n),now(n);
  auto dfs=[&](auto &&self,int pos,int par)->void{
    used[pos]=true;
    now[pos]=true;
    v.push_back(pos);
    for(auto to:g[pos]){
      if(!ret.empty())return;
      if(now[to]&&to!=par){
        for(auto z:v){
          if(!ret.empty()||z==to)ret.push_back(z);
        }
      }
      if(used[to])continue;
      self(self,to, pos);
    }
    now[pos]=false;
    v.pop_back();
  };
  for(int i=0;i<n;i++)if(!used[i])dfs(dfs,i,-1);
  return ret;
}
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  ll n,m;cin>>n>>m;
  Graph<P>g(n);
  vector<ll>u(m),v(m),a(m),b(m);
  rep(i,0,m){
    cin>>u[i]>>v[i]>>a[i]>>b[i];u[i]--;v[i]--;
    g[u[i]].EB(v[i],MP(a[i],b[i]),i);
    g[v[i]].EB(u[i],MP(a[i],b[i]),i);
  }
  auto cc=cycle_detection(g);
  set<int>ccst;
  for(auto z:cc)ccst.insert(z);
  auto ord=ascend(a);
  ll cnt=0;
  for(auto i:ord){
    res+=a[i]*(++cnt)+b[i];
  }
  if(m==n-1){
    cout<<res<<endl;
    return 0;
  }
  ll ret=res;
  Namori namori(g,true);
  vector<ll>pos(m);
  rep(i,0,m)pos[ord[i]]=i;
  vector<ll>ca(m+1);
  rep(i,0,m)ca[i+1]=ca[i]+a[ord[i]];
  rep(i,0,m){
    if(!ccst.count(u[i])||!ccst.count(v[i]))continue;
    chmax(ret,res-(ca[m]-ca[pos[i]+1])-(a[i]*(pos[i]+1)+b[i]));
  }
  //cout<<endl;
  cout<<ret<<endl;
  return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 96672
final_rank: 13

code_snippet: //#define _GLIBCXX_DEBUG

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};  
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge():id(-1){};
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
  Graph<T>ret(g.size());
  for(int i=0;i<g.size();i++){
    for(auto e:g[i]){
      int to = e.to;
      e.to = i;
      ret[to].push_back(e);
    }
  }
  return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v;
    T w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}
template<typename T>
struct Namori{
  const Graph<T>&g;
  int n;
  int edge_num=0;
  bool directed_forest = false;
  Namori(const Graph<T>&g, bool directed):g(g),n(g.size()){
    directed_forest = directed;
    int edge_num=0;
    for(auto &v:g)edge_num+=v.size();
    build();
  }
  vector<vector<int>>cycle;//連結成分の根となるサイクル サイクルではない場合も
  vector<vector<edge<T>>>cycle_edge;//辺属性
  vector<int>vn,en;//連結成分の頂点数、辺数
  Graph<T>forest;
  vector<int>root;
  vector<int>cycle_number;//頂点が属するサイクル番号 サイクルに属さなければ-1
  void build(){
    dfs_used.assign(n,false);
    dfs_now.assign(n,false);
    dfs_ver.clear();
    dfs_edge.clear();
    root.assign(n,-1);
    for(int i=0;i<n;i++){
      if(dfs_used[i])continue;
      cycle.emplace_back();
      cycle_edge.emplace_back();
      vn.push_back(0);
      en.push_back(0);
      build_dfs(i,-1,cycle.back(),cycle_edge.back());
      if(cycle.back().empty()){
        cycle.back().push_back(i);
      }
    }
    forest.resize(n);
    cycle_number.assign(n,-1);
    for(int i=0;i<cycle.size();i++){
      for(auto v:cycle[i])cycle_number[v]=i;
    }
    dfs_used.assign(n,false);
    for(int i=0;i<n;i++){
      if(cycle_number[i]!=-1)tree_dfs(i,vn[cycle_number[i]],en[cycle_number[i]],i);
    }
    for(int i=0;i<cycle.size();i++)en[i]>>=1;
  }
  void tree_dfs(int pos,int &vn,int &en,int r){
    vn++;
    dfs_used[pos]=true;
    root[pos]=r;
    for(auto e:g[pos]){
      en++;
      if(pos!=r&&dfs_used[e.to]&&!directed_forest)forest[pos].push_back(e);
      if(dfs_used[e.to]||cycle_number[e.to]!=-1)continue;
      forest[pos].push_back(e);
      tree_dfs(e.to,vn,en,r);
    }
  }
  vector<bool>dfs_used;
  vector<int>dfs_ver;
  vector<edge<T>>dfs_edge;
  vector<bool>dfs_now;
  void build_dfs(int pos, int par,vector<int>&cycle,vector<edge<T>>&cycle_edge){
    dfs_used[pos]=true;
    dfs_now[pos]=true;
    dfs_ver.push_back(pos);
    bool multiple_par=false;
    for(auto e:g[pos]){
      if(dfs_now[e.to]&&cycle.empty()&&(e.to!=par||multiple_par)){
        for(auto v:dfs_ver){
          if(!cycle.empty()||v==e.to)cycle.push_back(v);
        }
        for(auto ee:dfs_edge){
          cycle_edge.push_back(ee);
        }
        cycle_edge.push_back(e);
      }
      if(e.to==par)multiple_par=true;
      if(dfs_used[e.to])continue;
      dfs_edge.push_back(e);
      build_dfs(e.to,pos,cycle,cycle_edge);
      dfs_edge.pop_back();
    }
    dfs_now[pos]=false;
    dfs_ver.pop_back();
  }
};
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  ll n,m;cin>>n>>m;
  Graph<P>g(n);
  vector<ll>u(m),v(m),a(m),b(m);
  rep(i,0,m){
    cin>>u[i]>>v[i]>>a[i]>>b[i];u[i]--;v[i]--;
    g[u[i]].EB(v[i],MP(a[i],b[i]),i);
    g[v[i]].EB(u[i],MP(a[i],b[i]),i);
  }
  auto ord=ascend(a);
  ll cnt=0;
  for(auto i:ord){
    res+=a[i]*++cnt+b[i];
  }
  if(m==n-1){
    cout<<res<<endl;
    return 0;
  }
  ll ret=res;
  Namori namori(g,true);
  vector<ll>pos(m);
  rep(i,0,m)pos[ord[i]]=i;
  vector<ll>ca(m+1);
  rep(i,0,m)ca[i+1]=ca[i]+a[ord[i]];
  for(auto e:namori.cycle_edge[0]){
    //cout<<res spa ca[m]-ca[pos[e.id]+1] spa a[e.id] spa pos[e.id] spa b[e.id]<<endl;
    chmax(ret,res-(ca[m]-ca[pos[e.id]+1])-(a[e.id]*(pos[e.id]+1)+b[e.id]));
  }
  cout<<ret<<endl;
  return 0;
}
accuracy: 0.14814814814814814
time_ms: 170
memory_kb: 86004
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
//  auto begin = chrono::system_clock::now();
  int n, m;
  cin >> n >> m;
//  n = m = 200000;

  vector<vector<ll>> e(m, vector<ll>(4));
  vector<vector<pair<ll, ll>>> G(n);
  vector<ll> zi(n, 0);
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < 4; j++) {
      cin >> e[i][j];
      //if (j == 0) e[i][j] = 1;
      //else if (j == 1) e[i][j] = i + 1;
      //else e[i][j] = rand() % 200001 - 100000;
    }
//    e[0][1] = 2;
    e[i][0]--;
    e[i][1]--;
    G[e[i][0]].emplace_back(make_pair(e[i][1], i));
    G[e[i][1]].emplace_back(make_pair(e[i][0], i));
    zi[e[i][0]]++;
    zi[e[i][1]]++;
  }

  vector<ll> use(m, 0);
  if (m == n) {
    queue<ll> q;
    for (int i = 0; i < n; i++) {
      if (zi[i] == 1) q.push(i);
    }
    while (!q.empty()) {
      int v = q.front();
      q.pop();
      if (zi[v] == 1) {
	int v2 = 0;
	for (int i = 0; i < G[v].size(); i++) {
          if (use[G[v][i].second] == 0) {
	    v2 = G[v][i].first;
	    use[G[v][i].second] = 1;
	  }
	}
        //G[v].pop_back();
        zi[v]--;
        zi[v2]--;
        if (zi[v2] == 1) q.push(v2);
	/*
        for (int i = 0; i < G[v2].size(); i++) {
          if (G[v2][i].first == v) {
            swap(G[v2][i], G[v2].back());
            G[v2].pop_back();
            break;
          }
        }
        if (zi[v2] == 1) q.push(v2);
	*/
      }
    }
  }

  set<ll> st;
  if (m == n) {
    for (int i = 0; i < m; i++) {
      if (use[i] == 0) st.insert(i);
    }
    /*
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < (int) G[i].size(); j++) {
        st.insert(G[i][j].second);
      }
    }
    */
  }

  vector<vector<ll>> e2(m, vector<ll>(3)); // a, b, num
  for (int i = 0; i < m; i++) {
    e2[i][0] = e[i][2];
    e2[i][1] = e[i][3];
    e2[i][2] = i;
  }

  sort(e2.begin(), e2.end());

  ll bsum = 0;
  for (int i = 0; i < m; i++) bsum += e2[i][1];
  vector<ll> a_acc_rev(m);
  for (int i = m - 1; i >= 0; i--) {
    if (i == m - 1) a_acc_rev[i] = e2[i][0];
    else a_acc_rev[i] = e2[i][0] + a_acc_rev[i + 1];
  }

  ll ans_master = bsum;
  for (int i = 0; i < m; i++) {
    ans_master += (ll) (i + 1) * e2[i][0];
  }

  ll ans = ans_master;
  for (int i = 0; i < m; i++) {
    if (st.find(e2[i][2]) == st.end()) continue;
    ll tmp = ans_master;
    tmp -= (ll) (i + 1) * e2[i][0] + e2[i][1];
    if (i < m - 1) tmp -= a_acc_rev[i + 1];
    ans = max(ans, tmp);
  }

  cout << ans << '\n';
//  auto end = chrono::system_clock::now();
//  auto t = chrono::duration_cast<chrono::microseconds>(end - begin).count();
//  cout << t << endl;
}
accuracy: 1
time_ms: 210
memory_kb: 56732
final_rank: 8

code_snippet: #include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()
template<typename T1,typename T2> bool chmin(T1 &a,T2 b){if(a<=b)return 0; a=b; return 1;}
template<typename T1,typename T2> bool chmax(T1 &a,T2 b){if(a>=b)return 0; a=b; return 1;}
int dx[4]={0,1,0,-1}, dy[4]={1,0,-1,0};
long double eps = 1e-9;
long double pi = acos(-1);

class UnionFind{
    public:
    //親の番号を格納する。親だった場合は-(その集合のサイズ)
    vector<int> parent;

    UnionFind(int N){
        parent = vector<int>(N,-1);
    }

    int root(int A){
        if(parent[A] < 0) return A;
        return parent[A]=root(parent[A]);
    }

    int size(int A){
        return -parent[root(A)];
    }

    bool unite(int A, int B) {
        A = root(A), B = root(B);
        if(A == B) return false; 

        if(size(A) < size(B)) swap(A,B);
        parent[A] += parent[B];
        parent[B] = A;
        return true;
    }

    bool same(int A, int B){
        return root(A)==root(B);
    } 
};

vector<vector<array<int,2>>> v(200020);

bool used[200020];
int f = -1;
vector<int> namori;
bool dfs(int p, int pre){
    used[p] = 1;
    for(auto [nx,i]:v[p]){
        if(nx == pre)continue;
        if(used[nx]){
            f = nx;
            namori.push_back(i);
            if(f == p){
                return false;
            }
            return true;
        }
        else{
            if(dfs(nx, p)){
                namori.push_back(i);
                if(p == f) {
                    return false;
                }
                return true;
            }
        }
    }
    return false;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(20);

    int n,m;
    cin>>n>>m;
    array<ll,3> t[m];
    UnionFind uni(n);
    for(int i=0;i<m;i++){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        a--,b--;
        uni.unite(a,b);
        v[a].push_back({b,i});
        v[b].push_back({a,i});
        t[i] = {c,d,i};
    }
    assert(uni.size(0) == n);
    dfs(0,-1);
    sort(t,t+m);
    ll ans = 0;
    ll sum[m+1]={};
    int p[m]={};
    for(ll i=0;i<m;i++){
        sum[i+1] = sum[i] + t[i][0];
        ans += t[i][1] + t[i][0] * (i+1);
        p[t[i][2]] = i;
    }
    ll tmp = ans;
    for(auto i:namori){
        ll x = p[i];
        chmax(ans, tmp - t[x][1] - x*t[x][0] - sum[m] + sum[x]);
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 90
memory_kb: 33036
final_rank: 1