题目链接:http:// https://codeforces.com/contest/1266/problem/D
提示(note):
题意:
每组给你一个x,y,z,即d(x,y)=z表示y欠x z元钱,因为债务是可以转移的(a欠b l元,b欠c l元,可以转化为 a欠c l元),所以可以通过d的关系构成有向图,可以合并一些债务使得图中的权值减少,题目就演变成为在所有操作之后,图中的最小权值是多少,输出最后的图。
只需要考虑每个人欠多少钱,收到多少钱,收入和支出抵一下,最后会有欠钱的人和收钱的人,其中匹配一下就ok了。要想使得最后得债务关系最小,我们先统计每个人的净债务,那么我们就把赚钱的人给存起来,然后用负债的这些人的钱还给赚钱的就好了。
注意数据:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+10;
struct node{
int x,y,z;
};
int d[N];
signed main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
d[x]-=z;
d[y]+=z;
}
stack<int> aa,bb;
for(int i=1;i<=n;i++){
if(d[i]<0) aa.push(i);
if(d[i]>0) bb.push(i);
}
vector<node> ans;
while(aa.size()!=0){
int x=aa.top();
aa.pop();
int y=bb.top();
bb.pop();
int op=min(-d[x],d[y]);
d[x]+=op,d[y]-=op;
if(d[x]) aa.push(x);
if(d[y]) bb.push(y);
ans.push_back({x,y,op});
}
cout<<ans.size()<<"\n";
for(auto i:ans){
cout<<i.x<<" "<<i.y<<" "<<i.z<<"\n";
}
}