CodeForces - 1266D

Decreasing Debts

There are n people in this world, conveniently numbered 1 through n. They are using burles to buy goods and services. Occasionally, a person might not have enough currency to buy what he wants or needs, so he borrows money from someone else, with the idea that he will repay the loan later with interest. Let d(a,b) denote the debt of a towards b, or 0 if there is no such debt.

Sometimes, this becomes very complex, as the person lending money can run into financial troubles before his debtor is able to repay his debt, and finds himself in the need of borrowing money.

When this process runs for a long enough time, it might happen that there are so many debts that they can be consolidated. There are two ways this can be done:

Let d(a,b)>0 and d(c,d)>0 such that a≠c or b≠d. We can decrease the d(a,b) and d(c,d) by z and increase d(c,b) and d(a,d) by z, where 0<z≤min(d(a,b),d(c,d)).
Let d(a,a)>0. We can set d(a,a) to 0.
The total debt is defined as the sum of all debts:

Σd=∑a,bd(a,b)
Your goal is to use the above rules in any order any number of times, to make the total debt as small as possible. Note that you don’t have to minimise the number of non-zero debts, only the total debt.

Input
The first line contains two space separated integers n (1≤n≤105) and m (0≤m≤3⋅105), representing the number of people and the number of debts, respectively.

m lines follow, each of which contains three space separated integers ui, vi (1≤ui,vi≤n,ui≠vi), di (1≤di≤109), meaning that the person ui borrowed di burles from person vi.

Output
On the first line print an integer m′ (0≤m′≤3⋅105), representing the number of debts after the consolidation. It can be shown that an answer always exists with this additional constraint.

After that print m′ lines, i-th of which contains three space separated integers ui,vi,di, meaning that the person ui owes the person vi exactly di burles. The output must satisfy 1≤ui,vi≤n, ui≠vi and 0<di≤1018.

For each pair i≠j, it should hold that ui≠uj or vi≠vj. In other words, each pair of people can be included at most once in the output.

Examples
input
3 2
1 2 10
2 3 5
output
2
1 2 5
1 3 5
input
3 3
1 2 10
2 3 15
3 1 10
output
1
2 3 5
input
4 2
1 2 12
3 4 8
output
2
1 2 12
3 4 8
input
3 4
2 3 1
2 3 2
2 3 4
2 3 8
output
1
2 3 15

Note
In the first example the optimal sequence of operations can be the following:

Perform an operation of the first type with a=1, b=2, c=2, d=3 and z=5. The resulting debts are: d(1,2)=5, d(2,2)=5, d(1,3)=5, all other debts are 0;
Perform an operation of the second type with a=2. The resulting debts are: d(1,2)=5, d(1,3)=5, all other debts are 0.
In the second example the optimal sequence of operations can be the following:

Perform an operation of the first type with a=1, b=2, c=3, d=1 and z=10. The resulting debts are: d(3,2)=10, d(2,3)=15, d(1,1)=10, all other debts are 0;
Perform an operation of the first type with a=2, b=3, c=3, d=2 and z=10. The resulting debts are: d(2,2)=10, d(3,3)=10, d(2,3)=5, d(1,1)=10, all other debts are 0;
Perform an operation of the second type with a=2. The resulting debts are: d(3,3)=10, d(2,3)=5, d(1,1)=10, all other debts are 0;
Perform an operation of the second type with a=3. The resulting debts are: d(2,3)=5, d(1,1)=10, all other debts are 0;
Perform an operation of the second type with a=1. The resulting debts are: d(2,3)=5, all other debts are 0.

题意:

给定m条欠债人和债主的关系,让你简化这m条关系,思维题。
先记录每个人欠债的信息,包括别人欠他和他欠别人两种,然后,先将每个人的财产正负相抵,剩余的就是需要跟别人抵消的财产,然后欠别人钱的和别人欠他钱的相互抵消即可(题解瞎写的,我自己看得懂,自己理一理这个关系,不难)。

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 4e5;
struct node{
	int a,b;
	ll x;
}ans[N];
ll a[N],b[N];
int A[N],B[N];
int main(){
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i = 0;i < m;++i){
		int x,y,z;
		scanf("%d %d %d",&x,&y,&z);
		a[x] += z;
		b[y] += z;
	}
	int cut1 = 0,cut2 = 0;
	for(int i = 1;i <= n;++i){
		ll x=min(a[i],b[i]);
		a[i] -= x;
		b[i] -= x;
		if(a[i])A[cut1++] = i;
		if(b[i])B[cut2++] = i; 
	}
	int sum=0;
	for(int i = 0,j = 0;i < cut1;){
		if(a[A[i]] > b[B[j]]){
			ll x = b[B[j]];
			ans[sum++] = node{A[i],B[j],x};
			a[A[i]] -= x;
			b[B[j]] -= x;
			j++; 	
		}else{
			ll x = a[A[i]];
			ans[sum++] = node{A[i],B[j],x};
			a[A[i]] -= x;
			b[B[j]] -= x;
			i++;
			if(!b[B[j]])j++;
		}
	}
	printf("%d\n",sum);
	for(int i=0;i<sum;++i){
		printf("%d %d %lld\n",ans[i].a,ans[i].b,ans[i].x);
	}
	return 0;
}

写代码写出bug,实在找不出来,实在改不对就删了重写吧,别舍不得,别嫌浪费时间,真不浪费时间,重写一遍真的有用,长点记性吧。
还有赶紧复习Java吧,别写题了,快挂了。

赶紧美梦成真呀

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值