【codeforces gym】Increasing Costs
Description
给你一个\(n\)个点无重边无自环的无向连通图,每条边有一个边权,对于每一条边,询问去掉这条边之后有多少个点到\(1\)号点的最短路会发生改变
Solution
会用到一个叫做灭绝树的东西(这个名字好霸气qwq)
其实不算是什么特别高大上的玩意:灭绝树其实就是一个点灭绝后它的子树内的所有点都灭绝
然后所谓的“灭绝”其实可以理解为。。满足什么条件之类的,在不同的题目中有所不同(比如说在这题里面就是。。走不到)
然后这道题的话,因为是删边,我们可以将边也看成一个点
首先求出到\(1\)的最短路,然后对于原图中的一条边权为\(w\)的边\((i,j)\),如果说\(dis[j]=dis[i]+w\)的话,就在新图中连\((i,num)\)和\((num,j)\)的有向边,其中\(num\)表示的是这条边对应的节点
注意到如果说我们将一条边删掉,也就是相当于将这条边对应的节点\(num\)删掉,由于这条边删掉了,由这条边得到的最短路也就不能走了,对应到新图中就是\(num\)这个节点不能走到,接着那些的只能由它走到的后继也就不能走到了,以此类推
所以我们考虑用这样的方式建一棵树:我们将新图所有的边反过来建,然后对整个反过来的新图拓扑排序,从后往前处理每一个节点在树上面的\(fa\),那么处理到一个节点的时候,新图中所有能走到当前节点的点的\(fa\)都已经处理好了,然后我们将当前节点的\(fa\)设为所有能走到这个节点的那些点的\(lca\)
这样建完之后会发现,删掉一条边对应的点\(num\)之后不能走到的点其实就是其整个子树中的点
所以我们只要建出树之后计算一下每个节点的子树大小就好了
代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
const int N=4e5+10,TOP=20;
const ll inf=1LL<<60;
struct xxx{
int y,nxt,id,dis;
}a[N*2];
struct Data{
int node;
ll dis;
Data(){}
Data(int node1,ll dis1){node=node1; dis=dis1;}
friend bool operator < (Data x,Data y){return x.dis>y.dis;}
};
priority_queue<Data> q;
queue<int> q1;
vector<int> pre[N];
int lis[N];
int h[N],f[N][TOP+1],dep[N];
ll dis[N];
int vis[N],d[N],sz[N];
int n,m,tot,S;
void add(int x,int y,int dis,int id){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot; a[tot].id=id; a[tot].dis=dis;}
void print(vector<int> x){
for (int i=0;i<x.size();++i) printf("%d ",x[i]); printf("\n");
}
void dij(){
int u,v;
while (!q.empty()) q.pop();
for (int i=1;i<=n;++i) dis[i]=inf,vis[i]=false;
dis[S]=0;
q.push(Data(S,dis[S]));
while (!q.empty()){
v=q.top().node; q.pop();
if (vis[v]) continue;
vis[v]=1;
for (int i=h[v];i!=-1;i=a[i].nxt){
u=a[i].y;
if (vis[u]) continue;
if (dis[u]>dis[v]+a[i].dis){
dis[u]=dis[v]+a[i].dis;
q.push(Data(u,dis[u]));
}
}
}
for (int x=1;x<=n;++x){
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (dis[u]==dis[x]+a[i].dis){
pre[u].push_back(a[i].id+n);
pre[a[i].id+n].push_back(x);
++d[a[i].id+n];
++d[x];
}
}
}
}
int get_lca(int x,int y){
if (!x||!y) return x+y;
if (dep[x]<dep[y]) swap(x,y);
for (int i=TOP;i>=0;--i)
if (dep[f[x][i]]>=dep[y]) x=f[x][i];
if (x==y) return x;
for (int i=TOP;i>=0;--i)
if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
void topo(int n){
int u,v;
while (!q1.empty()) q1.pop();
for (int i=1;i<=n;++i)
if (d[i]==0) q1.push(i);
lis[0]=0;
while (!q1.empty()){
v=q1.front(); q1.pop();
lis[++lis[0]]=v;
for (int i=0;i<pre[v].size();++i){
u=pre[v][i];
--d[u];
if (!d[u]) q1.push(u);
}
}
}
void get_fa(int x){
int lca,Sz=pre[x].size();
if (Sz==0){
f[x][0]=0;
}
else if (Sz==1)
f[x][0]=pre[x][0];
else if (Sz>=2){
lca=get_lca(pre[x][0],pre[x][1]);
for (int i=2;i<Sz;++i)
lca=get_lca(lca,pre[x][i]);
f[x][0]=lca;
}
for (int i=1;i<=TOP;++i) f[x][i]=f[f[x][i-1]][i-1];
dep[x]=dep[f[x][0]]+1;
sz[x]=(x<=n);
}
void solve(){
topo(n+m);
for (int i=lis[0];i>=1;--i)
get_fa(lis[i]);
for (int i=1;i<=lis[0];++i)
sz[f[lis[i]][0]]+=sz[lis[i]];
}
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y,z;
scanf("%d%d",&n,&m);
memset(h,-1,sizeof(h));
tot=0;
for (int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z,i);
add(y,x,z,i);
}
S=1;
dij();
solve();
//for (int i=1;i<=n+m;++i) printf("%d " ,f[i][0]); printf("\n");
for (int i=1;i<=m;++i)
printf("%d\n",sz[i+n]);
}
【codeforces gym】Increasing Costs的更多相关文章
- 【codeforces 415D】Mashmokh and ACM(普通dp)
[codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=200 ...
- 【Codeforces Gym 100725K】Key Insertion
Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...
- 【77.78%】【codeforces 625C】K-special Tables
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
- 【15.07%】【codeforces 625A】Guest From the Past
time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...
- 【codeforces 757C】Felicity is Coming!
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【codeforces 750F】New Year and Finding Roots
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【13.77%】【codeforces 734C】Anton and Making Potions
time limit per test4 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- 【16.23%】【codeforces 586C】Gennady the Dentist
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- 【27.40%】【codeforces 599D】Spongebob and Squares
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
随机推荐
- 温习DL之一:梯度的概念
1.梯度的概念 梯度是一个矢量,表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向变化最快. 在微积分里面,对多元函数的参数求∂偏导数,把求得的各个参数的偏导数以向量的形式写 ...
- java中重要的多线程工具类
前言 之前学多线程的时候没有学习线程的同步工具类(辅助类).ps:当时觉得暂时用不上,认为是挺高深的知识点就没去管了.. 在前几天,朋友发了一篇比较好的Semaphore文章过来,然后在浏览博客的时候 ...
- 将项目托管到GitHub实现步骤
修改于:2017.1.14 第一步:先注册一个Github的账号 注册地址:Github官网注册入口 第二步:准备工作 gitHub网站使用Git版本管理工具来对仓库进行管理,但是它们并不等同. gi ...
- Shell 字符串处理、获取文件名和后缀名
http://blog.csdn.net/guojin08/article/details/38704823
- scrum立会报告+燃尽图(第二周第二次)
此作业要求参考: https://edu.cnblogs.com/campus/nenu/2018fall/homework/2247 一.小组介绍 组名:杨老师粉丝群 组长:乔静玉 组员:吴奕瑶.公 ...
- android 的helloworld没跑起来 原因
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com. ...
- Codeforces Round #341 (Div. 2) E. Wet Shark and Blocks dp+矩阵加速
题目链接: http://codeforces.com/problemset/problem/621/E E. Wet Shark and Blocks time limit per test2 se ...
- 0506-Scrum 项目 2.0视频
一.团队项目要求 应用NABCD模型,分析你们初步选定的项目,充分说明你们选题的理由. 录制为演说视频,上传到视频网站,并把链接发到团队博客上. 二.NABCD模型 选题:约拍平台——家教平台 1) ...
- 【转】SQL SERVER 中 sp_rename 用法
因需求变更要改表的列名,平常都是跑到Enterprise manager中选取服务器->数据库->表,然后修改表,这样太麻烦了,查了一下,可以用script搞定,代码如下: EXEC sp ...
- mysql DDL、DML、DCL、DQL区分
mysql [Structure Query Language] 的组成分4个部分: DDL [Data Mefinition Language] 数据定义语言 DML [Data ...