• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
AC_Artist.zig_zag
然而我依然在补题、
博客园    首页    新随笔    联系   管理    订阅  订阅

bzoj2001 城市建设

bzoj崩了3天了......本人目前处在无题可交的状态,郁闷啊。不过TY复活了,看到以前写过的代码有点小激动。

切入正题,这个题想了好久才写,主体还是分治,只是中间处理部分比较巧妙。这个题GYZ在wc上讲过,思路也很清晰,就是不太好写。

过程主要分两个部分(我直接粘解题报告了):

1. Contraction
把 L..R要修改的所有边权暂时标记为-∞;
对图做 MST;
此时观察图中不是-∞但被选入 MST的边集;
它们在 L..R的询问中也一定会被选入;
于是可以直接先用这些边把点集做合并操作。这样图的点数被缩小;
还原边权标记.
2. Reduction
把 L..R要修改的所有边权暂时标记为∞;
对图做 MST;
此时观察图中不是∞但没被选入 MST的边集;
它们在 L..R的询问中是无意义的,可以直接删除。这样图的边数被缩小;
还原边权标记.

这样做下去,等到L==R的时候,此时图已经被我们缩到了最小,做一遍mst即可。

注意contraction的时候缩完的边要累积到答案里面,然后就是每走到一个L==R的过程,就要令当前修改操作生效,因为它对后面的操作都有影响。

对于图的处理,最好是每层记录一个图,这样回溯的时候比较方便还原,另外要记录一个数组ci表示原来标号为i的边在当前边表中的位置。

city
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #define maxn 60000
  7 #define maxm 120000
  8 #define inf 2147483647
  9 using namespace std;
 10 struct et
 11 {
 12     int s,t,pos,val;
 13 }e[22][maxm],d[maxm],t[maxm];
 14 struct adj
 15 {
 16     int x,z;
 17 }q[maxn];
 18 int a[maxm],c[maxm];
 19 int f[maxn],sum[maxn],size[maxn];
 20 long long ans[maxm];
 21 int n,m,p;
 22 
 23 inline void fill(int tot)
 24 {
 25     for (int i=1;i<=tot;i++) 
 26         f[d[i].s]=f[d[i].t]=0,size[d[i].s]=size[d[i].t]=1;
 27 }
 28 inline int find(int i)
 29 {
 30     return (!f[i])?i:f[i]=find(f[i]);
 31 }
 32 inline void merge(int x,int y)
 33 {
 34     int fx=find(x),fy=find(y);
 35     if (size[fx]<=size[fy]) f[fx]=fy,size[fy]+=size[fx];
 36     else f[fy]=fx,size[fx]+=size[fy];
 37 }
 38 
 39 inline bool cmp(et a,et b)
 40 {
 41     return a.val<b.val;
 42 }
 43 
 44 inline void reduce(int &tot)
 45 {
 46     int tmp=0;
 47     fill(tot);
 48     sort(d+1,d+tot+1,cmp);
 49     for (int i=1;i<=tot;i++)
 50     {
 51         if (find(d[i].s)!=find(d[i].t))
 52         {
 53             merge(d[i].s,d[i].t);
 54             t[++tmp]=d[i];
 55             c[d[i].pos]=tmp;
 56         }
 57         else 
 58         if (d[i].val==inf)
 59         {
 60             t[++tmp]=d[i];
 61             c[d[i].pos]=tmp;
 62         }
 63     }
 64     for (int i=1;i<=tmp;i++) d[i]=t[i];
 65     tot=tmp;
 66 }
 67 
 68 inline void connect(int &tot,long long &cnt)
 69 {
 70     int tmp=0;
 71     fill(tot);
 72     sort(d+1,d+tot+1,cmp);
 73     for (int i=1;i<=tot;i++)
 74     {
 75         if (find(d[i].s)!=find(d[i].t)) 
 76         {
 77             merge(d[i].s,d[i].t);
 78             t[++tmp]=d[i];
 79         }
 80     }
 81     for (int i=1;i<=tmp;i++) f[t[i].s]=f[t[i].t]=0,size[t[i].s]=size[t[i].t]=1;
 82     for (int i=1;i<=tmp;i++)
 83         if (t[i].val!=-inf&&find(t[i].s)!=find(t[i].t))
 84             merge(t[i].s,t[i].t),cnt+=t[i].val;
 85     tmp=0;
 86     for (int i=1;i<=tot;i++)
 87         if (find(d[i].s)!=find(d[i].t)) 
 88         {
 89             t[++tmp]=d[i];
 90             c[d[i].pos]=tmp;
 91             t[tmp].s=find(d[i].s);
 92             t[tmp].t=find(d[i].t);
 93         }
 94     for (int i=1;i<=tmp;i++) d[i]=t[i];
 95     tot=tmp;
 96 }
 97 
 98 inline void solve(int l,int r,int now,long long cnt)
 99 {
100     int tot=sum[now];
101     if (l==r) a[q[l].x]=q[l].z;//修改生效
102     for (int i=1;i<=tot;i++) e[now][i].val=a[e[now][i].pos];
103     for (int i=1;i<=tot;i++) d[i]=e[now][i],c[d[i].pos]=i;  
104     if (l==r)
105     {
106         ans[l]=cnt;
107         fill(tot);
108         sort(d+1,d+tot+1,cmp);
109         for (int i=1;i<=tot;i++)
110             if (find(d[i].s)!=find(d[i].t))
111                 merge(d[i].s,d[i].t),ans[l]+=d[i].val;
112         return ;
113     }
114     for (int i=l;i<=r;i++) d[c[q[i].x]].val=-inf;
115     connect(tot,cnt);
116     for (int i=l;i<=r;i++) d[c[q[i].x]].val=inf;
117     reduce(tot);
118     for (int i=1;i<=tot;i++) e[now+1][i]=d[i];
119     sum[now+1]=tot;
120     int mid=(l+r)>>1;
121     solve(l,mid,now+1,cnt);
122     solve(mid+1,r,now+1,cnt);
123 }    
124 
125 int main()
126 {
127     //freopen("city.in","r",stdin);
128     //freopen("city.out","w",stdout);
129     scanf("%d%d%d",&n,&m,&p);
130     int x,y;
131     for (int i=1;i<=m;i++)
132     {
133         scanf("%d%d%d",&x,&y,&a[i]);
134         e[0][i].s=x; e[0][i].t=y; e[0][i].val=a[i];
135         e[0][i].pos=i;
136     }
137     for (int i=1;i<=p;i++)
138         scanf("%d%d",&q[i].x,&q[i].z);
139     sum[0]=m;
140     solve(1,p,0,0);
141     for (int i=1;i<=p;i++)
142         printf("%lld\n",ans[i]);
143     return 0;
144 }

 

代码冗长,速度还可以。

 

AC without art, no better than WA !
posted @ 2013-05-02 16:53  Zig_zag  阅读(954)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3