「日常训练」Battle Over Cities - Hard Version(PAT-TOP-1001)

题意与分析

题意真的很简单,实在不想讲了,简单说下做法吧。

枚举删除每个点,然后求最小生成树,如果这个路已经存在那么边权就是0,否则按照原来的处理,之后求花费,然后判整个图是否联通(并查集有几个root),如果不联通直接硬点花费是INF,然后处理输出答案即可。

一道最小生成树的模板题,比较有学习的意义。

代码

/*
 * Filename: pat_top_1001.cpp
 * Date: 2018-11-05
 */

#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
#define PB emplace_back
#define MP make_pair
#define fi first
#define se second
#define rep(i,a,b) for(repType i=(a); i<=(b); ++i)
#define per(i,a,b) for(repType i=(a); i>=(b); --i)
#define ZERO(x) memset(x, 0, sizeof(x))
#define MS(x,y) memset(x, y, sizeof(x))
#define ALL(x) (x).begin(), (x).end()

#define QUICKIO                      ios::sync_with_stdio(false);     cin.tie(0);                      cout.tie(0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)

using namespace std;
using pi=pair<int,int>;
using repType=int;
using ll=long long;
using ld=long double;
using ull=unsigned long long;

const int MAXN=505,MAXM=125005;
int n,m;
struct Edge
{
    int u,v,w;
    bool ok;
    Edge(int _u, int _v, int _w, bool _o):
        u(_u), v(_v), w(_w), ok(_o) {}
};
vector<Edge> edges;
vector<int> G[MAXN];
void add_edge(int u, int v, int w, bool ok)
{
    edges.PB(u,v,w,ok);
    G[u].PB(int(edges.size())-1);
}

int edges_ord[MAXM];
int pa[MAXN];
int find_pa(int x)
{
    return pa[x]==x?x:pa[x]=find_pa(pa[x]);
}
bool union_pa(int x,int y)
{
    int fx=find_pa(x),
        fy=find_pa(y);
    if(fx!=fy) pa[fx]=fy;
    else return false;
    return true;
}
int kruskal(int nope_pnt)
{
    int ans=0;
    iota(pa+1, pa+n+1, 1);
    rep(i,0,m-1)
    {
        int u=edges[edges_ord[i]].u,
            v=edges[edges_ord[i]].v,
            w=edges[edges_ord[i]].w;
        bool ok=edges[edges_ord[i]].ok;
        if(u==nope_pnt || v==nope_pnt) continue;
        if(union_pa(u,v))
            ans+=(1-ok)*w;
    }
    int cnt=0;
    rep(i,1,n) if(i!= nope_pnt && find_pa(i)==i)
        cnt++;
    if(cnt==1) return ans;
    else return INF;
}

int
main()
{
    scanf("%d%d", &n,&m);
    rep(i,1,m)
    {
        int u,v,w,o;
        scanf("%d%d%d%d", &u, &v, &w, &o);
        add_edge(u,v,w,o==1);
    }
    iota(edges_ord, edges_ord+m, 0);
    vector<int> ans_pnt;
    int ans_val=0;
    sort(edges_ord, edges_ord+m, [&](int x, int y) -> bool
                                 {
                                     if((1-edges[x].ok)*edges[x].w==
                                        edges[y].w*(1-edges[y].ok))
                                         return (edges[x].u<edges[y].u ||
                                                 (edges[x].u==edges[y].u &&
                                                  edges[x].v<edges[y].v));
                                     else return (1-edges[x].ok)*edges[x].w<
                                         edges[y].w*(1-edges[y].ok);
                                 });
    rep(nope_pnt,1,n)
    {
        int ans_tmp=kruskal(nope_pnt);
        if(ans_tmp>ans_val)
        {
            ans_val=ans_tmp;
            ans_pnt.clear();
            ans_pnt.PB(nope_pnt);
        }
        else if(ans_tmp==ans_val)
            ans_pnt.PB(nope_pnt);
    }
    if(ans_val==0) printf("0");
    else
    {
        rep(i,0,int(ans_pnt.size())-1)
        {
            printf("%d", ans_pnt[i]);
            if(i==int(ans_pnt.size())-1)
                printf("\n");
            else printf(" ");
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/samhx/p/PAT-TOP-1001.html

时间: 2024-11-09 11:20:17

「日常训练」Battle Over Cities - Hard Version(PAT-TOP-1001)的相关文章

「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)

题意与分析(CodeForces 540D) 代码 #include <iomanip> #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define MP make_pair #define PB push_back #define fi first #define se second #define ZERO(x) memset((x

「日常训练」School Marks(Codeforces Round 301 Div.2 B)

题意与分析(CodeForces 540B) 代码 #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define MP make_pair #define PB push_back #define fi first #define se second #define ZERO(x) memset((x), 0, sizeof(x)) #define

「日常训练」Ice Cave(Codeforces Round 301 Div.2 C)

题意与分析(CodeForces 540C) 这题坑惨了我....我和一道经典的bfs题混淆了,这题比那题简单. 那题大概是这样的,一个冰塔,第一次踩某块会碎,第二次踩碎的会掉落.然后求可行解. 但是这题...是冰塔的一层 也就是说,它只是个稍微有点限制的二维迷宫问题. 后面就好理解了,不过需要考虑下这种数据: 1 2 XX 1 1 1 1 这种数据答案是no.解决的方法可以考虑这样:分成两个数组来记录访问状态:vis数组和block数组. 代码 #include <queue> #inclu

「日常训练」Paths and Trees(Codeforces Round 301 Div.2 E)

题意与分析 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back #define fi first #define se second #define ZERO(x) memset((x), 0, sizeof(x)) #define ALL(x) (x).begin(),(x).end() #define rep(i, a, b) for (repType i = (a); i <= (b);

「日常训练」Woodcutters(Codeforces Round 303 Div.2 C)

这题惨遭被卡..卡了一个小时,太真实了. 题意与分析 (Codeforces 545C) 题意:给定\(n\)棵树,在\(x\)位置,高为\(h\),然后可以左倒右倒,然后倒下去会占据\([x-h,x]\)或者\([x,x+h]\)区间,如果不砍伐,占据\([x,x]\)区域. 问你最多砍多少棵树,砍树的条件是倒下去后占有的区间不能被其他树占据. 分析:在这条题目的条件下,这是一个傻逼贪心题.(然后我读错两次题目,怎么也想不出来贪心策略....) 很简单的策略:能往左倒往左倒,能往右倒往右倒.因

「日常训练」Regular Bridge(Codeforces Round 306 Div.2 D)

题意与分析 图论基础+思维题. 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back #define fi first #define se second #define ZERO(x) memset((x), 0, sizeof(x)) #define ALL(x) (x).begin(),(x).end() #define rep(i, a, b) for (repType i = (a); i &

「日常训练」Brackets in Implications(Codeforces Round 306 Div.2 E)

题意与分析 稍微复杂一些的思维题.反正这场全是思维题,就一道暴力水题(B). 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back #define fi first #define se second #define ZERO(x) memset((x), 0, sizeof(x)) #define ALL(x) (x).begin(),(x).end() #define rep(i, a, b) fo

「日常训练」All Friends(POJ-2989)

题意 分析 代码 #include <iostream> #include <cstring> #include <algorithm> #define MP make_pair #define PB emplace_back #define fi first #define se second #define ZERO(x) memset((x), 0, sizeof(x)) #define ALL(x) (x).begin(),(x).end() #define r

「日常训练」Skills(Codeforce Round Div.2 #339 D)

题意(CodeForces 614D) 每个人有\(n(n\le 10^5)\)个技能,技能等级都在\([0,10^9]\)的范围,每个技能有一个当前等级,所有技能的最高等级都为A.一个人的力量被记做以下两项的和: 1. 顶级技能的个数 *cf 2. 最低等级的技能 *cm 每个单位的钱能够提升一级力量.我们希望花尽可能少的钱,使得力量尽可能高. 分析 我二分的功力还是不足,要多努力.这题其实是一个非常明显的暴力:我们枚举提高到A的等级的个数(到不能提升为止),枚举这种情况下,我们能够令把多少人