Codeforces Round #378 (Div. 2)F

题目:一个带权连通无向图,给第i条边权值减1需要花费ci元,你一共有S元,求最小生成树。

容易得出钱全部花在一条边上是最优的。

我们先做一遍最小生成树。

然后我们枚举减哪一条边。

如果这条边是树上的,那么直接得出答案。

如果不是,我们可以用这一条边去替换u[i]、v[i]路径之间任意一条。所以我们用倍增(我sb了用的树链剖分)找到路径上最大的那一条替换,计算答案。

最后把这条边放进树里,再求一遍最小生成树就能输出方案了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define MAX(a,b) a>b?a:b
  5 #define N 210000 
  6 #define M 210000
  7 #define mem(a) memset(a,0,sizeof(a))
  8 #define rep(i,n) for (int i=1;i<=(n);i++)
  9 #define LL long long
 10 using namespace std;
 11 int uu,vv,root,ee,rr,ll,_,n,tot,e[M<<1],head[N],nex[N<<1];
 12 int id,p,q,m,top[N],siz[N],s[N],d[N],w[N],f[N],l[N<<2],r[N<<2];
 13 LL fuck,a[N<<2],orz,sum,S,ans,ma;
 14 bool intree[M];
 15 struct lbz
 16 {
 17     int u,v,d;
 18     LL w,c;
 19 }ed[M];
 20 void add(int u,int v,int c)
 21 {
 22     e[++ee]=v;nex[ee]=head[u];head[u]=ee;
 23 }
 24 void build(int s,int ll,int rr)
 25 {
 26     l[s]=ll;r[s]=rr; 
 27     if (ll==rr)
 28         a[s]=0;
 29     else
 30     {
 31         int mid=(ll+rr)>>1;
 32         build(s<<1,ll,mid);
 33         build((s<<1)+1,mid+1,rr);    
 34     }
 35 }
 36 void add(int s)
 37 {
 38     if (l[s]==r[s])
 39         a[s]=rr;
 40     else
 41     {
 42         if (r[s<<1]>=ll)
 43             add(s<<1);
 44         else
 45             add((s<<1)+1);
 46         a[s]=MAX(a[s<<1],a[(s<<1)+1]);
 47     }
 48 }
 49 void sea(int s)
 50 {
 51     if (l[s]>rr || r[s]<ll)
 52         return;
 53     if (l[s]>=ll&&r[s]<=rr)
 54         ans=MAX(ans,a[s]);
 55     else
 56     {
 57         sea(s<<1);
 58         sea((s<<1)+1);
 59     }
 60 }
 61 void dfs1(int u)
 62 {
 63     int j=head[u];
 64     siz[u]=1;
 65     while (j>0)
 66     {
 67         if (d[e[j]]==0)
 68         {
 69             d[e[j]]=d[u]+1;
 70             f[e[j]]=u;
 71             dfs1(e[j]);
 72             if (siz[e[j]]>siz[s[u]])
 73                 s[u]=e[j];
 74             siz[u]+=siz[e[j]];
 75         }
 76         j=nex[j];
 77     }
 78 }
 79 void dfs2(int u)
 80 {
 81     int j=head[u];
 82     if (s[u]!=0)
 83     {
 84         w[s[u]]=++tot;
 85         top[s[u]]=top[u];
 86         dfs2(s[u]);
 87     }
 88     while (j>0)
 89     {
 90         if (e[j]!=s[u]&&e[j]!=f[u])
 91         {
 92             w[e[j]]=++tot;
 93             top[e[j]]=e[j];
 94             dfs2(e[j]);
 95         }
 96         j=nex[j];
 97     }
 98 }
 99 void init()
100 {
101     orz=sum;
102     id=1;
103     mem(f);
104 }
105 bool cmp(lbz a,lbz b)
106 {
107     return a.w<b.w;
108 }
109 int find(int x)
110 {
111     if (f[x]==0) return x;
112     f[x]=find(f[x]);
113     return f[x];
114 }
115 int main()
116 {
117     scanf("%d%d",&n,&m);
118     rep(i,m)
119         scanf("%I64d",&ed[i].w);
120     rep(i,m)
121         scanf("%I64d",&ed[i].c);
122     rep(i,m)
123         scanf("%d%d",&ed[i].u,&ed[i].v);
124     scanf("%I64d",&S);
125     rep(i,m)
126         ed[i].d=i;
127     sort(ed+1,ed+1+m,cmp);
128     rep(i,m)
129     {
130         p=find(ed[i].u);
131         q=find(ed[i].v);
132         if (p!=q)
133         {
134             f[p]=q;
135             intree[i]=1;    
136             sum+=ed[i].w;
137         }
138     }
139     init();
140     rep(i,m)
141         if (intree[i]==1)
142         {
143             add(ed[i].u,ed[i].v,ed[i].w);
144             add(ed[i].v,ed[i].u,ed[i].w);
145         }
146     build(1,1,n-1);    
147     root=1;d[root]=1;top[root]=root;
148     dfs1(root);
149     dfs2(root);
150     rep(i,m)
151     {
152         if (intree[i]==0)continue;
153         if (d[ed[i].u]>d[ed[i].v])
154             swap(ed[i].u,ed[i].v);
155         ll=w[ed[i].v];rr=ed[i].w;
156         add(1);
157     }    
158     rep(i,m)
159     {
160         if (intree[i]==1)
161         {
162             fuck=sum-S/ed[i].c;
163             if (fuck<orz)
164             {
165                 orz=fuck;
166                 id=i;
167             }
168             continue;
169         }
170         uu=ed[i].u;vv=ed[i].v;
171         ma=0;
172         while (top[uu]!=top[vv])
173         {
174             if (d[top[uu]]<d[top[vv]])
175                 swap(uu,vv);
176             ans=0;ll=w[top[uu]];rr=w[uu];sea(1);
177             ma=MAX(ma,ans);
178             uu=f[top[uu]];
179         }
180         if (uu!=vv)
181         {
182             if (d[uu]<d[vv]) swap(uu,vv);
183             ans=0;ll=w[s[vv]];rr=w[uu];sea(1);
184             ma=MAX(ma,ans);
185         }
186         fuck=sum-ma+ed[i].w-S/ed[i].c;
187         if (fuck<orz)
188         {
189             orz=fuck;
190             id=i;
191         }
192     }
193     mem(f);mem(intree);
194     ed[id].w-=S/ed[id].c;
195     sort(ed+1,ed+1+m,cmp);
196     rep(i,m)
197     {
198         p=find(ed[i].u);
199         q=find(ed[i].v);
200         if (p!=q)
201         {
202             f[p]=q;
203             intree[i]=1;    
204         }
205     }
206     printf("%I64d\n",orz);
207     rep(i,m)
208         if (intree[i])
209             printf("%d %I64d\n",ed[i].d,ed[i].w);
210     return 0;
211         
212 }
View Code
#WhenWhoProblemLangVerdictTimeMemory
22090610 2016-11-07 11:28:10 lbz007 F - Drivers Dissatisfaction GNU C++ Accepted 608 ms 34700 KB
posted @ 2016-11-07 16:39  lbz007  阅读(175)  评论(0编辑  收藏  举报
Live2D