• CodeForces


    题目链接

    题目大意

      给你一堆债务关系,债务关系之间可以转移,让你简化债务关系,以使得债务关系中的债务之和最小。

    解题思路

      本来以为必须是本来就存在债务关系的一个集合之间才能互相转移,没想到没关系的也能转移。
      比如说这组数据:

    • 4 2
    • 1 2 12
    • 3 4 8

      就可以转化为:

    • 3 2 8
    • 1 2 4
    • 1 4 8

      好了,现在你读懂题了,应该可以A了吧债务关系的总值之所以能过减少,是因为之前有人借来了某些钱又借了出去,等于说借出去的这波钱倒了好几手,我们对于每个人都统计他借来的钱和借出去的钱,把他们相减就能去掉这些倒来的钱,之后再配对就行了。配对的时候只要保持每个人有借贷关系的人都至少能匹配上一个人并且自己的债务不变就行了。

    代码

    const int maxn = 2e5+10;
    const int maxm = 2e5+10;
    int n, m; 
    ll d[maxn];
    struct I {
    	int x, y; ll w;
    };
    int main() {
    	cin >> n >> m;
    	for (int i = 1, a, b, c; i<=m; ++i) {
    		scanf("%d%d%d", &a, &b, &c);
    		d[a] += c, d[b] -= c;
    	}
    	queue<Pll> a, b;
    	for (int i = 1; i<=n; ++i) {
    		if (d[i]>0) a.push({d[i], i});
    		else if (d[i]<0) b.push({d[i], i});
    	}
    	vector<I> ans;
    	while(!a.empty()) {
    		Pll t1 = a.front(); a.pop();
    		Pll t2 = b.front(); b.pop();
    		ll z = min(t1.x, abs(t2.x));
    		t1.x -= z;
    		t2.x += z;
    		if (t1.x) a.push(t1);
    		if (t2.x) b.push(t2);
    		ans.push_back({t1.y, t2.y, z});
    	}
    	cout << ans.size() << endl;
    	for (int i = 0; i<ans.size(); ++i) printf("%d %d %lld
    ", ans[i].x, ans[i].y, ans[i].w);
    	return 0;
    } 
    
  • 相关阅读:
    报错信息
    交通
    安装Charles代理
    安装Phabricator
    缓存更新问题
    最好的学习资料在官网
    mysql安装
    git使用
    vbox的centos系统挂载win共享目录做web目录www用户权限问题
    一句话解决windows下quick-cocos2d-x中player3打开黑屏问题
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/14447407.html
Copyright © 2020-2023  润新知