西电oj 1058 图论,贪心

西电oj 1058 图论,贪心

1058: 找子图

时间限制: 1 Sec  内存限制: 128 MB
提交: 15  解决: 11
[提交][状态][讨论版]

题目描述

现有一张无向图,有n个点m条边,每条边都有一个权值w,现要求从中找出一个子图,这个子图需满足以下特征:
1.子图可以为空。
2.若某条边的两个端点都在此子图中,则这条边在这个子图中。
3.若某条边的两个端点都不在此子图中,则这条边在这个子图外。
4.若某条边的两个端点一个在子图中,另一个不在,则这条边消失。
5.子图中所有边权值的和减去子图外所有边权值的和最大(不包含消失的边)。
输出这个最大值。

输入

多组数据

对于每组数据,第一行两个整数n,m(1<=n<=100000,1<=m<=500000)
接下来m行,每行三个整数u,v,w,表示在u和v间有一条权值为w的无向边(1<=u,v<=n,-1000<=w<=1000)

输出

 对于每组数据,输出答案。

样例输入

3 3

1 2 2

2 3 -1

1 3 3

2 1

1 2 -1

样例输出

4

1

题意:用c[u]记录从u出发的所有边的权值和。将原图分为子图u和子图v,ans=u的权值和-v的权值和=[(c[u1]+c[u2]+...+c[uN])-(c[v1]+c[v2]+...+c[vN])]/2;
对某子图u,所有c[u]的和=子图u里的边的权值和的两倍+u边界的边的权值和,因此,用c[u]的和-c[v]的和,边界被减掉了,剩下权值差的两倍,很好地处理了子图边界消失的情况。
对式子中,c[i]>0的点i加到子图u里,c[i]<0的点加到v里即可。
#include<iostream>

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<algorithm>

#include<vector>

#include<stack>

#include<queue>

#include<set>

#include<map>

#include<string>

#include<math.h>

#include<cctype>



using namespace std;



typedef long long ll;

const int maxn=1000100;

const int INF=(1<<29);

const double EPS=0.0000000001;

const double Pi=acos(-1.0);



ll c[maxn];

int n,m;



int main()

{

    while(cin>>n>>m){

        memset(c,0,sizeof(c));

        while(m--){

            int u,v;ll w;

            scanf("%d%d%lld",&u,&v,&w);

            c[u]+=w;c[v]+=w;

        }

        ll ans=0;

        for(int i=1;i<=n;i++){

            if(c[i]>0) ans+=c[i];

            else ans-=c[i];

        }

        ans/=2;

        cout<<ans<<endl;

    }

    return 0;

}
View Code

 

 

你可能感兴趣的:(图论)