zoukankan      html  css  js  c++  java
  • POJ 3723 Conscription

    http://poj.org/problem?id=3723

    这道题 把男生画一边 女生画一边 ---->是一个二部图的结构

    就很容易看出

    要pay最少 实际上就是找到一个连接所有点权值和最大的图 

    但是又要求 一个人只能使用一种关系减钱 所以不能有回路 ---->是一棵树

    所以就是求最大生成树

    有了前面并查集题目的经验 我们可以让i < N为女生 i >=N 作为男生 来维持这个并查集 

    那么就自然的使用Kruskal即可

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #define MAXV 20007
     6 #define MAXE 100007
     7 #define INF 0x3f3f3f3f
     8 using namespace std;
     9 
    10 struct Edge
    11 {
    12     int from, to, cost;
    13     Edge () {}
    14     Edge (int from, int to, int cost) : from(from), to(to), cost(cost) {}
    15 }edge[MAXE];
    16 int num = 0;
    17 int par[MAXV];
    18 int find(int x)
    19 {
    20     if (par[x] == x) return x;
    21     else return par[x] = find(par[x]);
    22 }
    23 void unite(int x, int y)
    24 {
    25     int px = find(x), py = find(y);
    26     if (px == py) return;
    27     par[py] = px;
    28 }
    29 bool same(int x, int y)
    30 {
    31     int px = find(x), py = find(y);
    32     return px == py;
    33 }
    34 
    35 bool cmp(Edge e1, Edge e2)
    36 {
    37     return e1.cost > e2.cost;
    38 }
    39 //主要就是画图 发现其实就是不能有回路 那就是最小生成树 偶不 最大生成树
    40 //书上提醒 在这个问题中 完全没有用到男女之间的二分图结构 但是在许多问题中 有特殊地结构 往往要考虑如何利用这个结构
    41 //也有像本题一样设置无用陷阱条件的题目!!
    42 int Kruskal()
    43 {
    44     int res = 0;
    45     sort(edge, edge+num, cmp);
    46     for (int i = 0; i < num; i++)
    47     {
    48         Edge e = edge[i];
    49         if (!same(e.from, e.to))
    50         {
    51             res += e.cost;
    52             unite(e.from, e.to);
    53         }
    54     }
    55     return res;
    56 }
    57 
    58 int main()
    59 {
    60     int R, N, M, T;
    61     freopen("in.txt", "r", stdin);
    62     scanf("%d", &T);
    63     while (T--)
    64     {
    65         scanf("%d%d%d", &N, &M, &R);//N girl , M boy
    66         for (int i = 0; i< N; i++) par[i] = i;
    67         for (int i = N; i < N+M; i++) par[i] = i;//i < N是girl i >= N 是Boy
    68         num = 0;
    69         for (int i = 0; i < R; i++)
    70         {
    71             int from, to, cost;
    72             scanf("%d%d%d", &from, &to, &cost);
    73             to += N;
    74             edge[num++] = Edge(from, to, cost);
    75             edge[num++] = Edge(to, from, cost);
    76         }
    77         int ans = 10000*(N+M);
    78         ans -= Kruskal();
    79         cout << ans << endl;
    80     }
    81     return 0;
    82 
    83 }
  • 相关阅读:
    【洛谷 4613】Olivander
    【洛谷 1385】密令
    【洛谷 4439】Aron
    【洛谷 3383】线性筛素数
    【洛谷 2412】查单词
    【洛谷 1980】计数问题
    【洛谷 3372】(模板)线段树 1
    Luogu P3743 kotori的设备
    Luogu P2340 [USACO03FALL]Cow Exhibition G
    Luogu P3047 [USACO12FEB]Nearby Cows G
  • 原文地址:https://www.cnblogs.com/oscar-cnblogs/p/6403894.html
Copyright © 2011-2022 走看看