zoukankan      html  css  js  c++  java
  • [树链剖分]hihocoder1883

    描述

    有一个无向图,有n个点,m1条第一类边和m2条第二类边。第一类边有边权,第二类边无边权。请为第二类的每条边定义一个边权,使得第二类边可能全部出现在该无向图的最小生成树上,同时要求第二类边的边权总和尽可能大。
    注:第二类边不会形成环

    输入

    第一行三个数n,m2,m1

    接下来m2行,每行两个数,描述一条第二类边,分别表示两个端点接下来m1行,每行三个数,描述一条第一类边,分别表示两个端点和边权

    对于30%的数据,n ≤ 5

    对于60%的数据,n ≤ 1000

    对于100%的数据,1 ≤ n ≤ 100000, m1 ≤ 2 × n, m2 < n

    输出

    输出一个数,表示第二类边的权值总和最大可能为多少。(若可能为无穷大则输出-1)

    样例输入
    5 2 3
    1 2
    4 5
    2 3 100
    3 4 100
    1 5 1000
    样例输出
    2000

    题解:

    将所有第二类边权当作0处理,先构造出生成树。

    之后对于不在生成树上的边e,我们尝试加入e,如果构成的环中有一条边大于e则将那条边用e代替更优。

    所以我们构造出生成树后,令第二类边权值为x = inf,每次对于一条不在生成树中的边权值w,让环上的第二类边权值x = min(x, w),即树上的链赋值操作,树链剖分即可。

      1 #include <bits/stdc++.h>
      2 
      3 #define ll long long
      4 #define ull unsigned long long
      5 #define st first
      6 #define nd second
      7 #define pii pair<int, int>
      8 #define pil pair<int, ll>
      9 #define pli pair<ll, int>
     10 #define pll pair<ll, ll>
     11 #define tiii tuple<int, int, int>
     12 #define pw(x) ((1LL)<<(x))
     13 #define lson l, m, rt<<1
     14 #define rson m+1, r, rt<<1|1
     15 #define sqr(x) ((x)*(x))
     16 #define SIZE(A) ((int)(A.size()))
     17 #define LENGTH(A) ((int)(A.length()))
     18 #define FIN freopen("A.in","r",stdin);
     19 #define FOUT freopen("A.out","w",stdout);
     20 using namespace std;
     21 /***********/
     22 
     23 template<typename T>
     24 bool scan (T &ret) {
     25     char c;
     26     int sgn;
     27     if (c = getchar(), c == EOF) return 0; //EOF
     28     while (c != '-' && (c < '0' || c > '9') ) c = getchar();
     29     sgn = (c == '-') ? -1 : 1;
     30     ret = (c == '-') ? 0 : (c - '0');
     31     while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
     32     ret *= sgn;
     33     return 1;
     34 }
     35 template<typename N,typename PN>inline N flo(N a,PN b){return a>=0?a/b:-((-a-1)/b)-1;}
     36 template<typename N,typename PN>inline N cei(N a,PN b){return a>0?(a-1)/b+1:-(-a/b);}
     37 template<typename T>inline int sgn(T a) {return a>0?1:(a<0?-1:0);}
     38 template<class T> int countbit(const T &n) { return (n==0)?0:(1+countbit(n&(n-1))); }
     39 template <class T1, class T2>
     40 bool gmax(T1 &a, const T2 &b) { return a < b? a = b, 1:0;}
     41 template <class T1, class T2>
     42 bool gmin(T1 &a, const T2 &b) { return a > b? a = b, 1:0;}
     43 template <class T> inline T lowbit(T x) {return x&(-x);}
     44 
     45 template<class T1, class T2>
     46 ostream& operator <<(ostream &out, pair<T1, T2> p) {
     47     return out << "(" << p.st << ", " << p.nd << ")";
     48 }
     49 template<class A, class B, class C>
     50 ostream& operator <<(ostream &out, tuple<A, B, C> t) {
     51     return out << "(" << get<0>(t) << ", " << get<1>(t) << ", " << get<2>(t) << ")";
     52 }
     53 template<class T>
     54 ostream& operator <<(ostream &out, vector<T> vec) {
     55     out << "("; for(auto &x: vec) out << x << ", "; return out << ")";
     56 }
     57 void testTle(int &a){
     58     while(1) a = a*(ll)a%1000000007;
     59 }
     60 const ll inf = 0x3f3f3f3f;
     61 const ll INF = 1e17;
     62 const int mod = 1e9+7;
     63 const double eps = 1e-5;
     64 const int N = 100000+10;
     65 const double pi = acos(-1.0);
     66 
     67 /***********/
     68 
     69 
     70 struct Edge{
     71     int x, y, w;
     72 };
     73 Edge edge1[N+N], edge2[N];
     74 vector<pii> ve[N];
     75 
     76 int n, m1, m2;
     77 int fa[N];
     78 int findf(int x) { return x == fa[x]? x: fa[x] = findf(fa[x]);}
     79 
     80 int dfn, f[N], fdis[N], d[N], size[N], son[N], top[N], st[N], en[N]; 
     81 struct Node {
     82     int maxval;
     83     int tag;
     84 };
     85 Node T[N<<2];
     86 int a[N];
     87 
     88 void pushup(int rt) {
     89     T[rt].maxval = max(T[rt<<1].maxval, T[rt<<1|1].maxval);
     90 }
     91 void pushdown(int rt) {//区间赋的值递增,之后赋的值必大于之前赋的值,故已有赋值则可跳过
     92     if(T[rt].tag) {
     93         if(!T[rt<<1].tag&&T[rt<<1].maxval > T[rt].tag)
     94             T[rt<<1].tag = T[rt].tag;
     95         if(!T[rt<<1|1].tag&&T[rt<<1|1].maxval > T[rt].tag)
     96             T[rt<<1|1].tag = T[rt].tag;
     97         T[rt].tag = 0;
     98     }
     99     if(T[rt].tag) {
    100         if(!T[rt<<1].tag&&T[rt<<1].maxval > T[rt].tag)
    101             T[rt<<1].tag = T[rt].tag;
    102         if(!T[rt<<1|1].tag&&T[rt<<1|1].maxval > T[rt].tag)
    103             T[rt<<1|1].tag = T[rt].tag;
    104         T[rt].tag = 0;
    105     }
    106 }
    107 void build(int l, int r, int rt) {
    108     if(l == r) {
    109         T[rt] = {a[l], 0};
    110         return ;
    111     }
    112     int m = (l+r) >> 1;
    113     build(lson);
    114     build(rson);
    115     pushup(rt);
    116 }
    117 void update(int L, int R, int val, int l, int r, int rt) {
    118     if(L <= l&&r <= R) {
    119         if(T[rt].tag == 0||T[rt].tag > val) T[rt].tag = val;
    120         return ;
    121     }
    122     pushdown(rt);
    123     int m = (l+r) >> 1;
    124     if(L <= m) update(L, R, val, lson);
    125     if(R > m) update(L, R, val, rson);
    126 }
    127 
    128 void dfs(int x){
    129     size[x] = 1;
    130     for(pii e: ve[x]) {
    131         int y = e.st;
    132         if(y != f[x]){
    133             f[y] = x, d[y] = d[x]+1;
    134             fdis[y] = e.nd;
    135             dfs(y), size[x] += size[y];
    136             if(size[y] > size[son[x]])
    137                 son[x] = y;
    138         }
    139     }
    140 }
    141 void dfs2(int x, int y){
    142     st[x] = ++dfn; top[x] = y;  a[dfn] = fdis[x];
    143     if(son[x]) dfs2(son[x], y);
    144     for(pii e: ve[x]) {
    145         int y = e.st;
    146         if(y != son[x]&&y != f[x])
    147             dfs2(y, y);
    148     }
    149     en[x]=dfn;
    150 }
    151 //查询x,y两点的lca
    152 int lca(int x,int y){
    153     for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]]) swap(x, y);
    154     return d[x]<d[y]?x:y;
    155 }
    156 //x是y的祖先,查询x到y方向的第一个点
    157 int lca2(int x, int y){
    158     int t;
    159     while(top[x]!=top[y])t=top[y],y=f[top[y]];
    160     return x==y?t:son[x];
    161 }
    162 //对x到y路径上的点进行操作
    163 void chain(int x, int y, int val){
    164     for(;top[x]!=top[y];x=f[top[x]]){
    165         if(d[top[x]]<d[top[y]]) swap(x, y);
    166         //change(st[top[x]],st[x]);
    167         update(st[top[x]], st[x], val, 1, n, 1); 
    168     }
    169     if(d[x]<d[y]) swap(x, y);
    170     //change(st[y],st[x]);
    171     update(st[y], st[x], val, 1, n, 1);
    172 }
    173 
    174 long long ans;
    175 bool solve(int l, int r, int rt) {
    176     if(T[rt].maxval != inf) return true;
    177     if(l == r) {
    178         if(T[rt].tag == 0) return false;
    179         ans += T[rt].tag;
    180         return true;
    181     }
    182     pushdown(rt);
    183     int m = (l+r) >> 1;
    184     return solve(lson) && solve(rson);
    185 }
    186 int main() {
    187     scanf("%d%d%d", &n, &m2, &m1);
    188     for(int i = 0, x, y; i < m2; i++) {
    189         scanf("%d%d", &x, &y);
    190         edge2[i] = {x, y, 0};
    191     }
    192     for(int i = 0, x, y, w; i < m1; i++) {
    193         scanf("%d%d%d", &x, &y, &w);
    194         edge1[i] = {x, y, w};
    195     }
    196 
    197     sort(edge1, edge1+m1, [](Edge e1, Edge e2) {  return e1.w < e2.w; });
    198     for(int i = 1; i <= n; i++) fa[i] = i;
    199     for(int i = 0; i < m2; i++) {
    200         Edge e = edge2[i];
    201         int fx = findf(e.x), fy = findf(e.y);
    202         if(fx != fy) {
    203             fa[fx] = fy;
    204             ve[e.x].push_back({e.y, inf});
    205             ve[e.y].push_back({e.x, inf});
    206         }
    207     }
    208     vector<Edge> tmp;
    209     for(int i = 0; i < m1; i++) {
    210         Edge e = edge1[i];
    211         int fx = findf(e.x), fy = findf(e.y);
    212         if(fx != fy) {
    213             fa[fx] = fy;
    214             ve[e.x].push_back({e.y, e.w});
    215             ve[e.y].push_back({e.x, e.w});
    216         }
    217         else tmp.push_back(e);//将e.x -> e.y路径上的边w = min(w, e.w);
    218     }
    219     
    220     dfs(1);
    221      dfs2(1, 1);
    222     build(1, n, 1);
    223     for(Edge e: tmp) {
    224         int x = e.x, y = e.y, w = e.w;
    225         int ancestor = lca(x, y);
    226         if(ancestor != x) {
    227             int xx = lca2(ancestor, x);
    228             chain(xx, x, w);
    229         }
    230         if(ancestor != y) {
    231             int yy = lca2(ancestor, y);
    232             chain(yy, y, w);
    233         }
    234     }
    235     printf("%lld
    ", solve(1, n, 1)? ans: -1);
    236     return 0;
    237 }
    View Code
  • 相关阅读:
    汉诺塔略写
    第六章实验报告
    第三次实验报告
    第五章 循环结构反思
    第二次实验报告
    第一次实验报告x
    第九章 结构体与共用体
    第八次实验报告
    第7章 数组实验
    第六章 函数和宏定义实验(2)
  • 原文地址:https://www.cnblogs.com/dirge/p/10424347.html
Copyright © 2011-2022 走看看