呵呵呵呵,这个sb题做了好久,然并卵,还是不对。

挖坑++

然而我感觉我做的对了,偷瞄了一下题解应该没什么问题。

这个题有n个点,n条边,所以是个基环树(我也不知道是不是这个名)

要每个点有联通,就是一个n个点的环,要是答案最小,那么我们就要保留下一些最大的链

现在我们考虑,因为一个点只有一个入度(n-1条边的话是一个严格从根节点单向向外的树),现在多了一个边,所以多了形成一个环

那先现在这个东西(基环树)就是一个环外面挂着一些严格向外延展的子树。

所以先考虑子树,对于每一个节点,贪心的保留一个权值最大的边连的儿子保留,其他的切掉(这里说的切掉是指重建),(这一步做完之后出来的东西就类似于树链剖分出来的重链)

再来考虑环,与环相连的子树,选择切掉,那么环是不用动的,选择不切,那么在环上对应的下条边是要切掉的。(这里打一个标记,判断切没切,然后,没切的话要找环上最小的边切开)

需要注意的是,可以不止一个基环树233333

 #include<bits/stdc++.h>
#define N 100005
#define LL long long
#define inf 1LL<<60
using namespace std;
inline LL ra()
{
LL x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
struct edge{
int to,next; LL v;
}e[N];
int head[N],cnt,n,start,d[N];
int top,ind,q[N],low[N],dfn[N],size[N],num,belong[N];
LL ans,sum,f[N],del,cst[N];
bool vis[N],cut,inq[N],can[N];
void insert(int x, int y, LL v)
{
e[++cnt].next=head[x]; e[cnt].to=y; e[cnt].v=v; head[x]=cnt;
}
void tarjan(int x)
{
dfn[x]=low[x]=++ind;
q[++top]=x; inq[x]=;
for (int i=head[x];i;i=e[i].next)
if (!dfn[e[i].to])
{
tarjan(e[i].to);
low[x]=min(low[e[i].to],low[x]);
}
else if (inq[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
if (low[x]==dfn[x])
{
++num;
int now=-;
while (now!=x)
{
now=q[top--];
belong[now]=num;
size[num]++;
inq[now]=;
}
}
}
void get_cost(int x)
{
can[x]=;
for (int i=head[x];i;i=e[i].next)
{
if (vis[e[i].to]) cst[x]=e[i].v;
if (e[i].to==start || !vis[e[i].to]) continue;
get_cost(e[i].to);
}
}
void solve_son(int x)
{
LL son_sum=,son_mx=;
for (int i=head[x];i;i=e[i].next)
{
son_sum+=e[i].v,son_mx=max(son_mx,e[i].v);
f[x]+=f[e[i].to];
solve_son(e[i].to);
}
f[x]+=son_sum-son_mx;
}
void dfs(int x)
{
LL son_del=-inf; can[x]=;
for (int i=head[x];i;i=e[i].next)
{
son_del=max(son_del,-cst[x]);
if (e[i].to==start) continue;
if (vis[e[i].to]) dfs(e[i].to);
else
{
solve_son(e[i].to);
ans+=f[e[i].to]+e[i].v;
son_del=max(son_del,e[i].v-cst[x]);
}
}
if (son_del>) cut=,ans-=son_del; else del=max(del,son_del);
}
int main()
{
n=ra();
for (int i=; i<=n; i++)
{
int x=ra();
LL v=(LL)ra();
if (x==i) ans+=v; else insert(x,i,v);
}
for (int i=; i<=n; i++)
if (!dfn[i]) tarjan(i);
int hehe=;
bool flag=;
for (int i=; i<=n; i++)
if (size[belong[i]]>)
{
if (hehe && hehe!=belong[i]) flag=;
hehe=belong[i];
vis[i]=;
}
for (int i=; i<=n; i++)
if (!vis[i]) {flag=; break;}
if (!flag)
{
cout<<""<<endl;
return ;
}
for (int i=; i<=n; i++)
if (vis[i] && !can[i])
{
start=i;
get_cost(i);
}
memset(can,,sizeof(can));
for (int i=; i<=n; i++)
if (vis[i] && !can[i])
{
cut=; del=-inf;
start=i; dfs(i);
if (!cut) ans-=del;
}
// for (int i=1; i<=n; i++) printf("%d ",f[i]);
cout<<ans<<endl;
return ;
}

最新文章

  1. js文章列表的树形结构输出
  2. Mysql性能优化三(分表、增量备份、还原)
  3. iOS小Tip之查看FPS
  4. WCF的同步和异步(以WPF连接为例)
  5. 《AngularJS高级程序设计》学习笔记
  6. 利用getchar()消除多余字符数据(主要是“回车”)
  7. Fiddler 日志
  8. apache开源项目--Jackrabbit
  9. jQuery中的DOM操作《思维导图》
  10. ubuntu 设置静态IP之后不能上网。
  11. 我的博客地址和github地址
  12. Windows系统版本判定那些事儿
  13. 利用uWSGI和nginx进行服务器部署
  14. BZOJ1069 SCOI2007 最大土地面积 凸包、旋转卡壳
  15. Linux软件源
  16. untiy 2d游戏平面直角坐标系的旋转应用
  17. 抱SQL SERVER大腿之我爱用视图(对大数据量的管理)
  18. Symbol 实现属性私有化的方式
  19. C#好书盘点
  20. 重构wm_concat,采用clob做为存储容器

热门文章

  1. 2020-2-18 restful的学习
  2. JMeter配置JDBC测试SQL Server/MySQL/ORACLE
  3. day07 集合
  4. Laradock 下安装Beast扩展
  5. ADV-292 计算行列式 java
  6. 六、ibatis1.2.8查询性能优化,实现百万数据zip导出
  7. H5地理定位获取用户当前位置、城市
  8. 「Luogu P3072 [USACO13FEB]周长Perimeter」
  9. Linux CentOS7 VMware 环境变量PATH、cp命令、mv命令、文档查看cat/more/less/head/tail——笔记
  10. Day9 - I - 不要62 HDU - 2089