cf 733f
给你很多条边,每条边有一个初始边权w1,然后还有一个值表示把这个边权减一的代价w2,然后给你一个预算budget,然后让你输出怎么选边之后构成的树的边权和最小(在用budget减少了边权之后),输出你选的每一条边以及该边此时的边权.
思路:首先显然预算都要用到你选的那棵树上w2最小的那条边上,然后就看你怎么选树,我的思路是:先prime选出最小生成树并记录现在的边上最小的w2,然后树链剖分,用线段树记录路径上边的边权的最大值.然后把所有的边按w2排序,当还有边的w2小于记录的最小的w2的时候,求出把这条边加进去并把形成的环上w1最大的那个边去掉能得到的答案,和之前的答案进行比较,从而找出最优的,由于最小生成树其实可能有很多种不同的我并不能保证我的思路对,但是考虑到最小生成树其实还是比较特殊的,可以推测不同的最小生成树得到的答案是一样的,我就这么做了,果然对了.
写道后面感觉好烦,就特别暴力了一下,反正后面的那部分耗时不大.
- #include <bits/stdc++.h>
- #define mid ((l+r)>>1)
- #define MAXN 200010 //节点数目
- using namespace std;
- typedef long long ll;
- vector<pair<int,int> >v[MAXN];
- int fa[MAXN];
- int deg[MAXN];
- int num[MAXN];
- int son[MAXN];
- int top[MAXN];
- int w[MAXN];//每个和对应子节点相连的边对应的编号
- int tot;//边的编号
- int tree[MAXN<<];
- void dfs1(int s,int d)
- {
- deg[s]=d,num[s]=,son[s]=;
- for(int i=;i<v[s].size();i++)
- {
- int t=v[s][i].first;
- if(t==fa[s])
- continue;
- fa[t]=s;
- dfs1(t,d+);
- num[s]+=num[t];
- if(num[t]>num[son[s]])
- son[s]=t;
- }
- }
- void dfs2(int s,int tp)
- {
- top[s]=tp;
- if(son[s])
- {
- w[son[s]]=++tot;
- dfs2(son[s],tp);
- }
- for(int i=;i<v[s].size();i++)
- {
- int t=v[s][i].first;
- if(t==fa[s]||t==son[s])
- continue;
- w[t]=++tot;
- dfs2(t,t);
- }
- }
- void update(int le,int ri,int val,int l,int r,int n)//区间更改,在这个程序中一定有le==ri,所以退化成单点更新
- {
- if(l==r)
- {
- tree[n]=val;
- return;
- }
- if(le<=mid)
- update(le,le,val,l,mid,n<<);
- else update(le,le,val,mid+,r,n<<|);
- tree[n]=max(tree[n<<],tree[n<<|]);
- }
- int query(int le,int ri,int l,int r,int n)
- {
- if(le==l&&ri==r)
- return tree[n];
- if(ri<=mid)
- return query(le,ri,l,mid,n<<);
- else if(le>mid)
- return query(le,ri,mid+,r,n<<|);
- else return max(query(le,mid,l,mid,n<<),query(mid+,ri,mid+,r,n<<|));
- }
- int find(int s,int t,int n)
- {
- int s1=top[s],t1=top[t],ans=;
- while(s1!=t1)
- {
- if(deg[s1]<deg[t1])
- {
- swap(s1,t1);
- swap(s,t);
- }
- ans=max(ans,query(w[s1],w[s],,n,));
- s=fa[s1];s1=top[s];
- }
- if(s!=t)
- {
- if(deg[s]<deg[t])
- swap(s,t);
- return max(ans,query(w[son[t]],w[s],,n,));
- }
- return ans;
- }
- int change(int s,int t,int c,int n)
- {
- int s1=top[s],t1=top[t];
- while(s1!=t1)
- {
- if(deg[s1]<deg[t1])
- {
- swap(s1,t1);
- swap(s,t);
- }
- update(w[s1],w[s],c,,n,);
- s=fa[s1];s1=top[s];
- }
- if(s!=t)
- {
- if(deg[s]<deg[t])
- swap(s,t);
- update(w[son[t]],w[s],c,,n,);
- }
- }
- vector<pair<int,int> >v2[MAXN];
- int val1[MAXN],val2[MAXN];
- bool sign[MAXN];
- int nu[MAXN];
- int fa2[MAXN];
- set<pair<int,int> >s;
- int minn=-;
- ll anss=;
- void prime(int t,int n)
- {
- sign[t]=true;
- for(int i=;i<v2[t].size();i++)
- {
- int t2=v2[t][i].first;
- if(nu[t2]&&val1[nu[t2]]>val1[v2[t][i].second])
- s.erase(s.find(make_pair(val1[nu[t2]],t2)));
- else if(nu[t2])
- continue;
- nu[t2]=v2[t][i].second;
- fa2[t2]=t;
- s.insert(make_pair(val1[nu[t2]],t2));
- }
- for(int i=;i<n;i++)
- {
- pair<int,int>temp=*s.begin();
- s.erase(s.begin());
- int t=temp.second;
- sign[t]=true;
- anss+=val1[nu[t]];
- v[fa2[t]].push_back(make_pair(t,nu[t]));
- if(minn==-||val2[nu[t]]<val2[minn])
- minn=nu[t];
- for(int i=;i<v2[t].size();i++)
- {
- int t2=v2[t][i].first;
- if(sign[t2])
- continue;
- if(nu[t2]&&val1[nu[t2]]>val1[v2[t][i].second])
- s.erase(s.find(make_pair(val1[nu[t2]],t2)));
- else if(nu[t2])
- continue;
- nu[t2]=v2[t][i].second;
- fa2[t2]=t;
- s.insert(make_pair(val1[nu[t2]],t2));
- }
- }
- }
- int a,b,c;
- pair<int,int>p[MAXN];
- int ss[MAXN],tt[MAXN];
- int main()
- {
- int n,m;
- scanf("%d%d",&n,&m);
- for(int i=;i<=m;i++)
- scanf("%d",&val1[i]);
- for(int i=;i<=m;i++)
- scanf("%d",&val2[i]);
- for(int i=;i<=m;i++)
- {
- scanf("%d%d",&a,&b);
- ss[i]=a;
- tt[i]=b;
- v2[a].push_back(make_pair(b,i));
- v2[b].push_back(make_pair(a,i));
- }
- int budget;
- scanf("%d",&budget);
- prime(,n);
- fa[]=;
- dfs1(,);
- tot=;
- dfs2(,);
- for(int i=;i<=n;i++)
- {
- a=i;
- for(int j=;j<v[i].size();j++)
- {
- b=v[i][j].first;
- c=val1[v[i][j].second];
- change(a,b,c,n-);//修改a,b之间路径值为c;
- }
- }
- for(int i=;i<=m;i++)
- {
- p[i].first=val2[i];
- p[i].second=i;
- }
- sort(p+,p++m);
- int maxn=;
- int fin=minn;
- int fansile;
- for(int i=;i<=m;i++)
- {
- int numb=p[i].second;
- if(numb==minn)
- break;
- int temp=find(ss[numb],tt[numb],n-);
- int curr=val1[numb]-temp;
- curr-=(budget/val2[numb])-(budget/val2[minn]);
- if(maxn>curr)
- {
- maxn=curr;
- fin=numb;
- fansile=temp;
- }
- }
- if(fin==minn)
- {
- printf("%lld\n",anss-budget/val2[minn]);
- for(int i=;i<=n;i++)
- {
- for(int j=;j<v[i].size();j++)
- {
- int numb=v[i][j].second;
- if(numb==minn)
- printf("%d %d\n",numb,val1[numb]-budget/val2[numb]);
- else
- printf("%d %d\n",numb,val1[numb]);
- }
- }
- }
- else
- {
- int caos=ss[fin],caot=tt[fin];
- int caos2=caos,caot2=caot;
- int mubiao;
- while()
- {
- int tops=top[caos2];
- int topt=top[caot2];
- if(tops==topt)
- {
- if(deg[caos2]<deg[caot2])
- mubiao=caos2;
- else mubiao=caot2;
- break;
- }
- else if(deg[tops]<deg[topt])
- caot2=fa[topt];
- else caos2=fa[tops];
- if(caos2==caot2)
- {
- mubiao=caos2;
- break;
- }
- }
- bool ok=false;
- int mubiao2;
- while(caos!=mubiao)
- {
- if(val1[nu[caos]]==fansile)
- {
- ok=true;
- mubiao2=nu[caos];
- break;
- }
- caos=fa2[caos];
- }
- while(!ok&&caot!=mubiao)
- {
- if(val1[nu[caot]]==fansile)
- {
- ok=true;
- mubiao2=nu[caot];
- break;
- }
- caot=fa2[caot];
- }
- printf("%I64d\n",anss+maxn-budget/val2[minn]);
- for(int i=;i<=n;i++)
- {
- for(int j=;j<v[i].size();j++)
- {
- if(v[i][j].second==mubiao2)
- continue;
- printf("%d %d\n",v[i][j].second,val1[v[i][j].second]);
- }
- }
- printf("%d %d\n",fin,val1[fin]-budget/val2[fin]);
- }
- return ;
- }
cf 733f的更多相关文章
- ORA-00494: enqueue [CF] held for too long (more than 900 seconds) by 'inst 1, osid 5166'
凌晨收到同事电话,反馈应用程序访问Oracle数据库时报错,当时现场现象确认: 1. 应用程序访问不了数据库,使用SQL Developer测试发现访问不了数据库.报ORA-12570 TNS:pac ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
- cf Round 613
A.Peter and Snow Blower(计算几何) 给定一个点和一个多边形,求出这个多边形绕这个点旋转一圈后形成的面积.保证这个点不在多边形内. 画个图能明白 这个图形是一个圆环,那么就是这个 ...
- ARC下OC对象和CF对象之间的桥接(bridge)
在开发iOS应用程序时我们有时会用到Core Foundation对象简称CF,例如Core Graphics.Core Text,并且我们可能需要将CF对象和OC对象进行互相转化,我们知道,ARC环 ...
- [Recommendation System] 推荐系统之协同过滤(CF)算法详解和实现
1 集体智慧和协同过滤 1.1 什么是集体智慧(社会计算)? 集体智慧 (Collective Intelligence) 并不是 Web2.0 时代特有的,只是在 Web2.0 时代,大家在 Web ...
- CF memsql Start[c]UP 2.0 A
CF memsql Start[c]UP 2.0 A A. Golden System time limit per test 1 second memory limit per test 256 m ...
- CF memsql Start[c]UP 2.0 B
CF memsql Start[c]UP 2.0 B B. Distributed Join time limit per test 1 second memory limit per test 25 ...
- CF #376 (Div. 2) C. dfs
1.CF #376 (Div. 2) C. Socks dfs 2.题意:给袜子上色,使n天左右脚袜子都同样颜色. 3.总结:一开始用链表存图,一直TLE test 6 (1)如果需 ...
- CF #375 (Div. 2) D. bfs
1.CF #375 (Div. 2) D. Lakes in Berland 2.总结:麻烦的bfs,但其实很水.. 3.题意:n*m的陆地与水泽,水泽在边界表示连通海洋.最后要剩k个湖,总要填掉多 ...
随机推荐
- bootstrap-滚动监听
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- IComparable<T> Vs. IComparer<T> System.Comparison<T>
Well they are not quite the same thing as IComparer<T> is implemented on a type that is capabl ...
- linux下搭建sock5代理
VPN大家耳熟能详,但是socks用到的人比较少,那什么是socks呢?请看第二段或者百度百科,socks分别有4和5两个版本,现在5为主流.工作中经常用VPN访问国外,但是同时国内的速度又慢了,让人 ...
- yum:在Red Hat和Fedora中使用
1.列出已安装包: yum list installed--------->输出的结果可能在屏幕上一闪而过.所以最好把已安装包的列表重定义到一个文件中.然后是使用more/less查看 yum ...
- Python基础语法,基本数据类型及相关操作
---恢复内容开始--- python文件 文件开头要有 #!/usr/bin/ python --在linux中是告诉系统phthon的路径是在/usr/bin/ python目录下 ...
- [ActionScript 3.0] 对代码加密的有效方法
package { import flash.display.Loader; import flash.display.Sprite; import flash.net.LocalConnection ...
- MVC 访问IFrame页面Session过期后跳转到登录页面
Web端开发时,用户登录后往往会通过Session来保存用户信息,Session存放在服务器,当用户长时间不操作的时候,我们会希望服务器保存的Session过期,这个时候,因为Session中的用户信 ...
- js判断浏览器
function myBrowser(){ var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串 ; if (isOpera) { ret ...
- [转载]Vivado轻松实现IP封装
Vivado轻松实现IP封装 1.新建一个测试工程 工程化的设计方法是离不开工程的,第一步往往都是新建工程,后面我会学习去工程化的开发方法,可能会更加高效. 2.利用向导完成IP封装 2.1.启动IP ...
- Java 2D API - 2. Graphics 入门
Java 2D API强大而复杂,不过大多时候我们只需使用java.awt.Graphcis类的部分功能.下面的内容将覆盖大多数的常见应用. Graphics 类中的方法大致可以分为两类: Draw ...