hdu 6187 Destroy Walls

来源:互联网 发布:java 二进制上传文件 编辑:程序博客网 时间:2024/05/31 18:37
Long times ago, there are beautiful historic walls in the city. These walls divide the city into many parts of area.Since it was not convenient, the new king wants to destroy some of these walls, so he can arrive anywhere from his castle. We assume that his castle locates at (0.6∗√2,0.6∗√3).There are n towers in the city, which numbered from 1 to n. The ith's location is (xi,yi). Also, there are m walls connecting the towers. Specifically, the ith wall connects the tower ui and the tower vi(including the endpoint). The cost of destroying the ith wall is wi.Now the king asks you to help him to divide the city. Firstly, the king wants to destroy as less walls as possible, and in addition, he wants to make the cost least.The walls only intersect at the endpoint. It is guaranteed that no walls connects the same tower and no 2 walls connects the same pair of towers. Thait is to say, the given graph formed by the walls and towers doesn't contain any multiple edges or self-loops.Initially, you should tell the king how many walls he should destroy at least to achieve his goal, and the minimal cost under this condition.

Input

There are several test cases.For each test case:The first line contains 2 integer n, m.Then next n lines describe the coordinates of the points.Each line contains 2 integers xi,yi.Then m lines follow, the ith line contains 3 integers ui,vi,wi|xi|,|yi|≤1053≤n≤100000,1≤m≤2000001≤ui,vi≤n,ui≠vi,0≤wi≤10000

Output

For each test case outout one line with 2 integers sperate by a space, indicate how many walls the king should destroy at least to achieve his goal, and the minimal cost under this condition.

Sample Input

4 4-1 -1-1 11 11 -11 2 12 3 23 4 14 1 2

Sample Output

1 1

【题意】

给你n个点,m条边,构成一张图,显然这个图可能会有环路,现在已知每条边都有一个权值,现在让你删掉一些边,使得图中不存在环。问你最少要删掉几条边,在删掉这么多边的情况下问你所删掉的边的最小权值和是多少。

【分析】

显然,我们直接按照题意做显然是有点麻烦的,所以我们把问题转化一下,因为要保证最后的图不含环路,所以可以看成最后一定是一棵树或者多棵树,于是我们就直接求一个生成树,也就是最后剩下的边。因为要保证删除的边的权值和最小,也就是我们的生成树的权值最大,于是就可以想到题目就是求一个最大生成树,然后用所有的边权和,然后减去这个最大生成树的权值就是最后的答案,

【代码】

#include<iostream>#include<cstdio>#include<cstring>#include<string.h>#include<algorithm>#include<vector>#include<cmath>#include<stdlib.h>#include<time.h>#include<stack>#include<set>#include<map>#include<queue>#include<sstream>using namespace std;#define rep0(i,l,r) for(int i = (l);i < (r);i++)#define rep1(i,l,r) for(int i = (l);i <= (r);i++)#define rep_0(i,r,l) for(int i = (r);i > (l);i--)#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)#define MS0(a) memset(a,0,sizeof(a))#define MS_1(a) memset(a,-1,sizeof(a))#define MSinf(a) memset(a,0x3f,sizeof(a))#define MSfalse(a) memset(a,false,sizeof(a))#define inf 0x3f3f3f3f#define lson i<<1,l,mid#define rson ((i<<1)|1),mid+1,r#define uint unsigned inttypedef pair<int,int> PII;#define A first#define B second#define pb push_back#define mp make_pair#define ll long long#define eps 1e-8inline void read1(int &num) {    char in;    bool IsN=false;    in=getchar();    while(in!='-'&&(in<'0'||in>'9')) in=getchar();    if(in=='-') {        IsN=true;        num=0;    } else num=in-'0';    while(in=getchar(),in>='0'&&in<='9') {        num*=10,num+=in-'0';    }    if(IsN) num=-num;}inline void read2(int &a,int &b) {    read1(a);    read1(b);}inline void read3(int &a,int &b,int &c){    read1(a);    read1(b);    read1(c);}inline void read1(ll &num) {    char in;    bool IsN=false;    in=getchar();    while(in!='-'&&(in<'0'||in>'9')) in=getchar();    if(in=='-') {        IsN=true;        num=0;    } else num=in-'0';    while(in=getchar(),in>='0'&&in<='9') {        num*=10,num+=in-'0';    }    if(IsN) num=-num;}inline void read2(ll &a,ll &b) {    read1(a);    read1(b);}inline void read3(ll &a,ll &b,ll &c){    read1(a);    read1(b);    read1(c);}inline void read1(double &num) {    char in;    double Dec=0.1;    bool IsN=false,IsD=false;    in=getchar();    while(in!='-'&&in!='.'&&(in<'0'||in>'9'))        in=getchar();    if(in=='-') {        IsN=true;        num=0;    } else if(in=='.') {        IsD=true;        num=0;    } else num=in-'0';    if(!IsD) {        while(in=getchar(),in>='0'&&in<='9') {            num*=10;            num+=in-'0';        }    }    if(in!='.') {        if(IsN) num=-num;        return ;    } else {        while(in=getchar(),in>='0'&&in<='9') {            num+=Dec*(in-'0');            Dec*=0.1;        }    }    if(IsN) num=-num;}inline void read2(double &a,double &b){    read1(a);    read1(b);}inline void read3(double &a,double &b,double &c){    read1(a);    read1(b);    read1(c);}inline void hdu(void){    srand(time(0));    printf("%d\n",rand()%5217+1000);}///-----------------------------------------------------------------------------------const int maxm = 1e5+10;struct E{    int from,to,value;}edge[maxm];bool cmp(E a,E b){    return a.value>b.value;}int n,m;int pre[maxm];int fin(int ind){    return pre[ind]==ind?ind:(pre[ind]=fin(pre[ind]));}void init(int n){    rep1(i,1,n) pre[i] = i;}int main(void){//    freopen("in.txt","r",stdin);    while(scanf("%d%d",&n,&m)!=EOF)    {        init(n);        int a,b;        while(n--) read2(a,b);        int ans = 0;        rep0(i,0,m)         {            read3(edge[i].from,edge[i].to,edge[i].value);            ans+=edge[i].value;        }        sort(edge,edge+m,cmp);        int ans2 = m;        rep0(i,0,m)        {            a = fin(edge[i].from);            b = fin(edge[i].to);            if(a!=b)            {                ans2--;                pre[a] = b;                ans-=edge[i].value;            }        }        printf("%d %d\n",ans2,ans);    }    return 0;}
原创粉丝点击