电报
来源:互联网 发布:淘宝一元抢购在哪里 编辑:程序博客网 时间:2024/05/17 08:30
题目大意
n个点,每个点出度均为1的有向图。
你可以将j->k改成j->l,代价为c[j]。
求最小代价,使得有向图变成一个环。
贪心
我们把问题描述成删去若干条边,删除每条边都有代价,最小代价使得每个联通块都是一条链(这样才能连成环)。
假如一个点有k个入度,至少k-1个要被删掉。
对于树的情况贪心保留最大代价的入边。
环上至少一条边要删去,再讨论一下即可。
注意特判初始所有点连成一个环的情况。
#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;const int maxn=100000+10,inf=2000000000;int a[maxn],b[maxn],c[maxn],g[maxn],p[maxn],belong[maxn];int h[maxn],go[maxn],nxt[maxn];int h2[maxn],g2[maxn],n2[maxn];ll f[maxn];bool pd[maxn],bz[maxn];int i,j,k,l,t,n,m,tot,top,cnt,wdc,mi;ll ans,sum,num;bool czy;int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f;}void add(int x,int y){ go[++tot]=y; nxt[tot]=h[x]; h[x]=tot;}void add2(int x,int y){ g2[++cnt]=y; n2[cnt]=h2[x]; h2[x]=cnt;}void dfs(int x){ if (pd[a[x]]){ belong[x]=++tot; bz[x]=1; wdc=a[x]; return; } if (belong[a[x]]){ belong[x]=belong[a[x]]; return; } pd[x]=1; dfs(a[x]); belong[x]=belong[a[x]]; if (wdc) bz[x]=1; if (x==wdc) wdc=0; pd[x]=0;}void dg(int x){ int t=h[x],mx=0; ll l=0; while (t){ dg(go[t]); mx=max(mx,c[go[t]]); l+=(ll)c[go[t]]; t=nxt[t]; } ans+=(ll)l-mx;}void work(int x){ top=0; t=h2[x]; while (t){ p[++top]=g2[t]; t=n2[t]; } fo(i,1,top) if (!bz[p[i]]&&bz[a[p[i]]]){ dg(p[i]); f[a[p[i]]]+=(ll)c[p[i]]; g[a[p[i]]]=max(g[a[p[i]]],c[p[i]]); } fo(i,1,top) if (bz[p[i]]) b[a[p[i]]]=c[p[i]]; mi=inf; fo(i,1,top) if (bz[p[i]]) mi=min(mi,c[p[i]]); sum=0; fo(i,1,top) if (bz[p[i]]) sum+=f[p[i]]; num=sum+mi; sum=0; fo(i,1,top) if (bz[p[i]]) sum+=min(f[p[i]],f[p[i]]-g[p[i]]+(ll)b[p[i]]); fo(i,1,top) if (bz[p[i]]){ sum-=min(f[p[i]],f[p[i]]-g[p[i]]+(ll)b[p[i]]); num=min(num,sum+f[p[i]]-g[p[i]]+(ll)b[p[i]]); sum+=min(f[p[i]],f[p[i]]-g[p[i]]+(ll)b[p[i]]); } ans+=num;}int main(){ freopen("telegraph.in","r",stdin);freopen("telegraph.out","w",stdout); n=read(); fo(i,1,n){ a[i]=read();c[i]=read(); add(a[i],i); } tot=0; fo(i,1,n) if (!belong[i]){ wdc=0; dfs(i); } if (tot==1){ czy=1; fo(i,1,n) if (!bz[i]){ czy=0; break; } if (czy){ printf("0\n"); return 0; } } fo(i,1,n) add2(belong[i],i); fo(wdc,1,tot) work(wdc); printf("%lld\n",ans);}
阅读全文
0 0
- 电报
- 电报 编码
- 局域网电报系统
- 有线电报这玩意
- 地方贝多芬八封电报
- 电报电话的原理和作用
- 美国电话电报公司 AT&T
- CD光盘和电报的编码
- [雅礼集训6-23] T1 电报
- 两份矛盾的电报--中国出兵朝鲜档案解密
- 台达0.4KW伺服上电报AL013
- 编程乐趣:获取12306的所有车站电报码
- 有情报称,克里姆林宫已经破解电报服务
- 摩尔斯电报码 解码算法 (Python 语言描述)
- 中文电码(姓名 电报码 VISA DS160 美国签证)在线查询工具
- 数据结构 第14讲 神秘电报密码——哈夫曼编码
- 华为优招:电报中用点(.)表示1,用中划线(-)表示0,序列中间用#号分隔;
- 鹿晗示爱崩溃不了你,无法忘却的前任的前任的前任之电报故事
- python环境配置-Linux系统
- LeetCode(4)
- 【0036】SQL数据操纵语言INSERT,UPDATE,DELETE
- Swift_for while循环,if语句
- Hibernate笔记(二)
- 电报
- 通过system调用颜色函数
- Maven学习笔记(一)
- HTML5实现图片淡入淡出效果
- java使用jbarcode生成条形码
- 无需安装redis,在线练习
- android代码规范
- sqlload导入txt文件
- Encoder