zoukankan      html  css  js  c++  java
  • 2018 ACM-ICPC青岛现场赛 B题 Kawa Exam 题解 ZOJ 4059

    题意:
    BaoBao正在进行在线考试(都是选择题),每个题都有唯一的一个正确答案,但是考试系统有m个bug(就是有m个限制),每个bug表示为第u个问题和第v个问题你必须选择相同的选项,题目问你,如果你修好了第i个bug,BaoBao最高可以取得多少分。

    题目数量1e5
    BUG数量1e5(真多)
    答案范围1e5

    思路:首先,如果出现了bug,导致{a1,a2,...,an}n个题目必须选择一样的结果,那么最高得分肯定是众数的出现次数。我们发现bug是具有传递性的,如果bug连成了一个环,而且你只修复其中一个bug,那么这个bug的修复是对整个考试系统是没有任何影响的,所以我们不需要考虑这个环内的边,然后我们可以把这些环抠出来,缩成一个点,具体的缩点方法很多,也可以把整个块拉成一条链或者拓扑排序弄一弄,或者tarjan缩一下,我是用tarjan缩点的,这样整个图就是一个树了。
    现在修一个bug就相当于断了一条边,一棵树就被切成两半了,我们需要同时得到两边的众数的个数是多少,这时候就有一个算法叫dsu on tree了,这是一个复杂度十分科学的暴力算法,http://codeforces.com/problemset/problem/600/E 这个题是一个dsu on tree的裸题,就是让你求每个子树的众数,不会这个算法的可以去学一下,做完这个题你就发现你会做子树内众数的个数了,现在还有个问题,子树外的怎么求呢?我们可以反过来做,一开始把所有的节点加进贡献里面去,然后dsu on tree的时候,询问子树众数的添加删除的时候,我们只要做相反的操作就行了。

    具体细节还挺多的。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn = 100010;struct Edge {
      4     int to,next,id;
      5     Edge(int _to=0,int _next=-1,int _id=0):to(_to),next(_next),id(_id) {};
      6 } edge[maxn*2];
      7 int head[maxn],etot;
      8 inline void addedge(int u,int v,int id) {
      9     edge[++etot]=Edge(v,head[u],id);
     10     head[u]=etot;
     11 }
     12 vector<int> nodes[maxn];
     13 int Cnt;
     14 int dfn[maxn],low[maxn],tot;
     15 bool Vis[maxn];
     16 int S[maxn],top;
     17 int id[maxn];
     18 void tarjan(int x,int fa) {
     19     low[x]=dfn[x]=++tot;
     20     S[++top]=x;
     21     Vis[x]=1;
     22     for(register int i=head[x]; ~i; i=edge[i].next) {
     23         int v=edge[i].to;
     24         if(v==fa) {fa=0;continue;}
     25         if(!dfn[v]) {
     26             tarjan(v,x);
     27             low[x]=min(low[x],low[v]);
     28         } else if(Vis[v])
     29             low[x]=min(low[x],dfn[v]);
     30     }
     31     if(low[x]==dfn[x]) {
     32         Cnt++;
     33         while(1) {
     34             int now=S[top--];
     35             Vis[now]=0;
     36             id[now]=Cnt;
     37             nodes[Cnt].push_back(now);
     38             if(now==x) break;
     39         }
     40     }
     41 }
     42 int a[maxn],ans[maxn];
     43 vector<int>v[maxn];
     44 vector<int>edg[maxn],eid[maxn];
     45 int summ;
     46 bool vis[maxn];
     47 int sz[maxn],son[maxn];
     48 vector<int>vv;
     49 int getid(int x) {
     50     return lower_bound(vv.begin(),vv.end(),x)-vv.begin()+1;
     51 }
     52 void init(int now,int pre=-1){
     53     vis[now]=1;
     54     sz[now]=v[now].size();
     55     for(int it:v[now])vv.push_back(a[it]);
     56     for(int to:edg[now]){
     57         if(to==pre)continue;
     58         init(to,now);
     59         sz[now]+=sz[to];
     60         if(!son[now]||sz[to]>sz[son[now]])
     61             son[now]=to;
     62     }
     63 }
     64 int tp[maxn],tp2[maxn],cnt[maxn],cnt2[maxn],Max=0,Max2=0;
     65 bool big[maxn];
     66 void update(int nows,int pre,int val){
     67     for(int now:v[nows]){
     68         tp[cnt[a[now]]]--;
     69         cnt[a[now]]+=val;
     70         tp[cnt[a[now]]]++;
     71         if(cnt[a[now]]>Max)
     72             Max=cnt[a[now]];
     73         if(!tp[Max])Max--;
     74         tp2[cnt2[a[now]]]--;
     75         cnt2[a[now]]-=val;
     76         tp2[cnt2[a[now]]]++;
     77         if(cnt2[a[now]]>Max2)
     78             Max2=cnt2[a[now]];
     79         if(!tp2[Max2])Max2--;
     80     }
     81     for(int to:edg[nows])
     82         if(to!=pre&&big[to]==0)
     83             update(to,nows,val);
     84 }
     85 void update2(int nows,int pre,int val){
     86     for(int now:v[nows]){
     87         tp2[cnt2[a[now]]]--;
     88         cnt2[a[now]]+=val;
     89         tp2[cnt2[a[now]]]++;
     90         if(cnt2[a[now]]>Max2)
     91             Max2=cnt2[a[now]];
     92         if(!tp2[Max2])Max2--;
     93     }
     94 }
     95 int temp;
     96 void dfs(int now,int pre=-1,int kep=0,int id=0){
     97     int tid=0;
     98     for(register int i=0;i<edg[now].size();i++){
     99         int to=edg[now][i];
    100         if(to==son[now])tid=eid[now][i];
    101         if(to==pre||to==son[now])continue;
    102         dfs(to,now,0,eid[now][i]);
    103     }
    104     if(son[now])
    105         dfs(son[now],now,1,tid),big[son[now]]=1;
    106     update(now,pre,1);
    107     ans[id]=Max+Max2-temp;
    108     big[son[now]]=0;
    109     if(!kep)update(now,pre,-1);
    110 }
    111 void init2(int now,int pre=-1){
    112     for(int it:v[now])a[it]=getid(a[it]);
    113     update2(now,0,1);
    114     for(int to:edg[now]){
    115         if(to==pre)continue;
    116         init2(to,now);
    117     }
    118 }
    119 void solve(int now){
    120     vv.clear();
    121     init(now);
    122     for(register int i=0;i<=sz[now];i++)tp[i]=tp2[i]=cnt[i]=cnt2[i]=big[i]=0;Max=Max2=0;
    123     sort(vv.begin(),vv.end());
    124     vv.erase(unique(vv.begin(),vv.end()),vv.end());
    125     init2(now);
    126     summ+=Max2;
    127     temp=Max2;
    128     dfs(now);
    129 }
    130 int main()
    131 {
    132     int T;
    133     scanf("%d",&T);
    134     while(T--){
    135         int n,m;
    136         scanf("%d%d",&n,&m);
    137         for(register int i=1;i<=n;i++)head[i]=-1,dfn[i]=son[i]=vis[i]=Vis[i]=0,v[i].clear(),edg[i].clear(),eid[i].clear();
    138         etot=tot=Cnt=top=0;
    139         for(register int i=1;i<=n;i++)scanf("%d",a+i);
    140         for(register int i=1;i<=m;i++){
    141             int u,v;
    142             scanf("%d%d",&u,&v);
    143             addedge(v,u,i);
    144             addedge(u,v,i);
    145         }
    146         for(register int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);
    147         for(register int i=1;i<=n;i++)v[id[i]].push_back(i);
    148         summ=0;
    149         for(register int i=1;i<=n;i++){
    150             for(register int j=head[i];~j;j=edge[j].next){
    151                 int u=id[i],to=id[edge[j].to];
    152                 if(u==to){
    153                     ans[edge[j].id]=0;
    154                     continue;
    155                 }
    156                 edg[u].push_back(to);eid[u].push_back(edge[j].id);
    157             }
    158         }
    159         for(register int i=1;i<=Cnt;i++)
    160             if(!vis[i])
    161                 solve(i);
    162         for(register int i=1;i<=m;i++){
    163             if(i>1)putchar(' ');
    164             printf("%d",ans[i]+summ);
    165         }
    166         puts("");
    167     }
    168     return 0;
    169 }
  • 相关阅读:
    idea 配置 scala
    Error contacting service. It is probably not running.
    ipc.Client: Retrying connect to server: .../10.0.0.27:10020. Already tried 6 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1 SECONDS)
    hadoop安装配置
    WordCount-JAVA版
    scp、rsync、xsync
    我所经历的开题
    无情的岁月之流水一般的一年级
    数据挖掘中易犯的几大错误【转载,侵删】
    如何摧毁程序员的效率?【转载,侵删】
  • 原文地址:https://www.cnblogs.com/xseventh/p/9986194.html
Copyright © 2011-2022 走看看