hdu 2480 贪心+简单并查集

本文针对一道关于盗宝联盟的问题进行解析,问题设定在一个由多个城市组成的国家中,每个城市间通过不同类型的路径相连,路径上藏有宝藏。文章详细阐述了如何利用贪心算法和并查集解决此问题,实现利益最大化。

Steal the Treasure

Time Limit: 10000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 775    Accepted Submission(s): 213

Problem Description
The alliance of thieves decides to steal the treasure from country A. There are n cities in country A. Cities are connected by directional or bidirectional road. To avoid the risk, the king of country A divides his treasure and hides them in some place on the road.   The alliance has found out the secret of the king. They get a map of country A which shows the location and the quantity of treasure on each road. In order to make the maximum profit and reduce the least loss, the alliance determines to send n thieves respectively to each city (one city one thief). At the appointed time, each thief chooses one road (if there is a road and notice that the road may have direction) to get to its corresponding city. Then he can steal the treasure on that road. After stealing, all the thieves return back to their base immediately.   The heads of the alliance wonder to know the quantity of the treasure they can steal at most.
 
Input
There are multiple cases. Input is terminated by EOF.   For each case, the first line contains two integers n (1<=n<=1000) and m (0<=m<=n*(n-1)/2), representing the number of cities and the number of roads in country A. The following m lines, each line contains four integers x, y (1<=x, y<=n, x≠y), d (0<=d<=1), w (0<=w<=1000), which means that there is a road from city x to city y, d=0 shows this road is bidirectional and d=1 shows it is directional and x the starting point, w is the quantity of treasure on the road.   We guarantee that the road (x, y) and (y, x) will never appear together in the same case.
 
Output
For each case, output the maximum quantity of treasure the alliance can get.
 
Sample Input
2 1 1 2 0 10 5 5 1 2 1 0 1 3 1 10 2 3 0 20 3 4 0 30 4 2 1 40
 
Sample Output
10 100
 题目大意:有n个城市,这些城市由m条道路连通,每一条道路都有着一定的权值(财富),这些道路有的是可以双向连通的,有的是单向的,只能从一个点出发,现在每一个城市都有着一个小偷,在特定时刻,这些小偷可以从这个城市前往任一条道路(如果可以),并拿走这条道路上的财富,现在问你最多能拿到多少财富。
思路分析:首先肯定是贪心,将边按照边权从大到小排序,到底能不能拿这个路上的财富是由他的端点城市决定的,对于有向边,如果起点未被标记,那么就拿走财富,标记起点,对于无向边,如果有一个点没被标记,就标记那个点,否则就用并查集将其缩为一点。
代码:
#include <iostream>
#include<cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1000+10;
struct node
{
    int x,y;
    int d,w;
};
node edge[maxn*maxn/2];
int fa[maxn];
int root(int x)
{
    return (x==fa[x])?x:fa[x]=root(fa[x]);
}
bool cmp(node a,node b)
{
    return a.w>b.w;
}
bool vis[maxn];
int n,m;
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;i++)
            fa[i]=i;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d%d",&edge[i].x,&edge[i].y,&edge[i].d,&edge[i].w);
        }
        sort(edge,edge+m,cmp);
        int ans=0;
        for(int i=0;i<m;i++)
        {
            int fx=root(edge[i].x);
            int fy=root(edge[i].y);
            if(vis[fx]&&vis[fy]) continue;
            if(edge[i].d==1&&vis[fx]) continue;
            ans+=edge[i].w;
            if(edge[i].d==1) vis[fx]=true;
            else
            {
                if(fx==fy) vis[fx]=true;
                else if(vis[fx]) vis[fy]=true;
                else if(vis[fy]) vis[fx]=true;
                else fa[fx]=fy;//缩点
            }
        }
        printf("%d\n",ans);
    }
}

 

转载于:https://www.cnblogs.com/xuejianye/p/5701520.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值