zoukankan      html  css  js  c++  java
  • UOJ14 DZY Loves Graph

    DZY开始有 nn 个点,现在他对这 nn 个点进行了 mm 次操作,对于第 ii 个操作(从 11 开始编号)有可能的三种情况:

    1. Add a b: 表示在 aa 与 bb 之间连了一条长度为 ii 的边(注意,ii是操作编号)。保证 1a,bn1≤a,b≤n。
    2. Delete k: 表示删除了当前图中边权最大的k条边。保证 kk 一定不会比当前图中边的条数多。
    3. Return: 表示撤销第 i1i−1 次操作。保证第 11 次操作不是 Return 且第 i1i−1 次不是 Return 操作。

    请你在每次操作后告诉DZY当前图的最小生成树边权和。如果最小生成树不存在则输出 00。

    输入格式

    第一行两个正整数 n,mn,m。表示有 nn 个点 mm 个操作。 接下来 mm 行每行描述一个操作。

    输入格式

    对于每一个操作输出一行一个整数表示当前最小生成树边权和。

    样例一

    input

    2 2
    Add 1 2
    Return
    
    

    output

    1
    0
    
    

    样例二

    input

    5 10
    Add 2 1
    Add 3 2
    Add 4 2
    Add 5 2
    Add 2 3
    Return
    Delete 1
    Add 2 3
    Add 5 2
    Return
    
    

    output

    0
    0
    0
    10
    10
    10
    0
    0
    15
    0
    
    

    样例三

    见样例数据下载

    正解:并查集+各种奇怪维护

    解题报告:

      调试了两个多小时才AC,而且还蒯了别人的题解。

      传送门:http://vfleaking.blog.uoj.ac/blog/15

      我讲不太清楚,直接看vfk的博客吧。

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXM = 500011;
     21 int n,m,cnt;//cnt统计树边
     22 LL ans;
     23 int father[MAXM],last[MAXM];//分别表示最小生成树中的所在块的祖先和这条边断掉之后的所在块的祖先(前提,这条边在最小生成树中)
     24 //int stack[MAXM];
     25 int size[MAXM],top;
     26 char ch[12];
     27 LL num[MAXM];
     28 vector<int>q;
     29 struct ask{
     30     int type,x,y;
     31 }Q[MAXM];
     32 
     33 inline int getint()
     34 {
     35        int w=0,q=0;
     36        char c=getchar();
     37        while((c<'0' || c>'9') && c!='-') c=getchar();
     38        if (c=='-')  q=1, c=getchar();
     39        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     40        return q ? -w : w;
     41 }
     42 
     43 inline int find(int x){
     44     if(father[x]!=x) return find(father[x]);
     45     return father[x];
     46 }
     47 
     48 inline void delet(int x){
     49     int u;
     50     while(x--) {
     51     u=q[q.size()-1]; q.pop_back();
     52     //u=stack[top]; top--;
     53     if(last[u]!=-1) {
     54         ans-=u; cnt--;
     55         
     56         int y=father[u];
     57         while(y)
     58         {
     59             size[y]-=size[u];
     60             if(y==father[y]) break;
     61         }
     62         //if(father[x])  size[father[x]]-=size[x];
     63         father[last[u]]=last[u];
     64     }
     65     }
     66 }
     67 
     68 inline void work(){
     69     n=getint(); m=getint();
     70     for(int i=1;i<=m;i++) {
     71     scanf("%s",ch);
     72     if(ch[0]=='A')  Q[i].type=1,Q[i].x=getint(),Q[i].y=getint();
     73     else if(ch[0]=='D') Q[i].type=2,Q[i].x=getint();
     74     else Q[i].type=3;
     75     }
     76     for(int i=1;i<=n;i++) father[i]=i,size[i]=1;
     77     int x,y;
     78     for(int i=1;i<=m;i++) {
     79     if(Q[i].type==1) {
     80         //stack[++top]=i;
     81         q.push_back(i);
     82         x=find(Q[i].x); y=find(Q[i].y);
     83         if(x!=y) {//加入最小生成树,后面的肯定不如前面的编号小的更优
     84         if(size[x]>size[y]) swap(x,y);//交换,按秩
     85         last[i]=x; 
     86         father[x]=y; size[y]+=size[x];
     87         ans+=i; cnt++;
     88         }
     89         else last[i]=-1;//不在最小生成树中
     90     }
     91     else if(Q[i].type==2) {
     92         if(Q[i+1].type==3) {
     93         //printf("%lld
    ",num[top-Q[i].x]);
     94         printf("%lld
    ",num[q.size()-Q[i].x]);
     95         continue;
     96         }else delet(Q[i].x);
     97     }
     98     else {
     99         if(Q[i-1].type==1) delet(1);
    100     }
    101 
    102     if(cnt==n-1) {//构成最小生成树
    103         //num[top]=ans;
    104         num[q.size()]=ans;
    105         printf("%lld
    ",ans);
    106     }
    107     else { 
    108         //num[top]=0;
    109         num[q.size()]=0;
    110         printf("0
    "); }
    111     }
    112 }
    113 
    114 int main()
    115 {
    116   work();
    117   return 0;
    118 }
  • 相关阅读:
    Hibernate session.save()实体类,主键增长问题
    安装原版 Windows 7 后需要安装的微软更新 和 必备系统组件
    如何使用站群程序来批量建网站?
    Android图片优化指南
    SQLite为何要用C语言来开发?
    Kotlin使用率达35%,Java要退位了?
    JavaScript的几种循环使用方式及性能解析
    30 分钟理解 CORB 是什么
    PHP 字符串相关常识
    那些10w+的公众号都在写什么?
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5765212.html
Copyright © 2011-2022 走看看