4016: [FJOI2014]最短路径树问题 点分治
2016-01-19 19:42
465 查看
首先dijkstra一下最短路径树,然后点分治。
每次对每个子树进行操作,f[i][0]表示深度为i时的最长路径,f[i][1]表示深度为i时当前最长路径的方案数,两个数组倒一倒~不要忘记清零。
qwq开始犯了sb错误居然水过了。。。
每次对每个子树进行操作,f[i][0]表示深度为i时的最长路径,f[i][1]表示深度为i时当前最长路径的方案数,两个数组倒一倒~不要忘记清零。
qwq开始犯了sb错误居然水过了。。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #define inf 2000000000 #define N 30005 using namespace std; int n,m,K,cnt,ans1,ans2,root,sz,sum; int fm ,head ,head_ ,size ; int deep ,dis ,q ,fa ; struct node {int v,id;} heap[N<<2]; int next[N<<1],list[N<<1],key[N<<1]; int next_[N<<2],list_[N<<2],key_[N<<2]; int f [2],g [2]; bool vis ; vector <pair<int,int> > a ; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void insert(int x,int y,int z) { next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; key[cnt]=z; } inline void insert_(int x,int y,int z) { next_[++cnt]=head_[x]; head_[x]=cnt; list_[cnt]=y; key_[cnt]=z; } inline void push(node x) { heap[++sz]=x; int now=sz; while (now&&heap[now].v<heap[now>>1].v) { swap(heap[now],heap[now>>1]); now>>=1; } } inline void pop() { heap[1]=heap[sz--]; int now=1; while (now<=(sz>>1)) { int next=now<<1; if (next<sz&&heap[next].v>heap[next+1].v) next++; if (heap[now].v<heap[next].v) return; swap(heap[now],heap[next]); now=next; } } inline void dijkstra() { for (int i=1;i<=n;i++) dis[i]=inf,vis[i]=0; dis[1]=0; push((node){0,1}); while (sz) { int x=heap[1].id; pop(); if (vis[x]) continue; vis[x]=1; for (int i=head_[x];i;i=next_[i]) if (dis[list_[i]]>dis[x]+key_[i]) { dis[list_[i]]=dis[x]+key_[i]; push((node){dis[list_[i]],list_[i]}); } } } void dfs(int x) { vis[x]=1; for (int i=head_[x];i;i=next_[i]) if (!vis[list_[i]]&&dis[list_[i]]==dis[x]+key_[i]) { insert(x,list_[i],key_[i]); insert(list_[i],x,key_[i]); dfs(list_[i]); } } void getroot(int x) { size[x]=1; fm[x]=0; for (int i=head[x];i;i=next[i]) if (list[i]!=fa[x]&&!vis[list[i]]) { fa[list[i]]=x; getroot(list[i]); size[x]+=size[list[i]]; fm[x]=max(fm[x],size[list[i]]); } fm[x]=max(fm[x],sum-size[x]); if (fm[x]<fm[root]) root=x; } /*void getdeep(int x,int fa,int deep,int dis) { if (deep>K) return; if (dis>g[deep][0]) g[deep][0]=dis,g[deep][1]=1; else if (dis==g[deep][0]) g[deep][1]++; for (int i=head[x];i;i=next[i]) if (list[i]!=fa&&!vis[list[i]]) getdeep(list[i],x,deep+1,dis+key[i]); }*/ void work(int x,int nowsum) { vis[x]=1; f[0][1]=1; for (int i=head[x];i;i=next[i]) if (!vis[list[i]]) { // getdeep(list[i],-1,1,key[i]); int t=0,w=1; q[1]=list[i]; deep[list[i]]=1; fa[list[i]]=x; dis[list[i]]=key[i]; while (t!=w) { int xx=q[++t]; int k=deep[xx]; if (k>K) break; if (dis[xx]>g[k][0]) g[k][0]=dis[xx],g[k][1]=0; if (dis[xx]==g[k][0]) g[k][1]++; for (int j=head[xx];j;j=next[j]) if (!vis[list[j]]&&list[j]!=fa[xx]) { fa[list[j]]=xx; deep[list[j]]=deep[xx]+1; dis[list[j]]=dis[xx]+key[j]; q[++w]=list[j]; } } for (int j=1;j<=K;j++) { if (g[j][0]+f[K-j][0]>ans1) ans1=g[j][0]+f[K-j][0],ans2=0; if (g[j][0]+f[K-j][0]==ans1) ans2+=g[j][1]*f[K-j][1]; } for (int j=1;j<=K;j++) { if (g[j][0]>f[j][0]) f[j][0]=g[j][0],f[j][1]=0; if (g[j][0]==f[j][0]) f[j][1]+=g[j][1]; g[j][0]=g[j][1]=0; } } for (int i=0;i<=K;i++) f[i][0]=f[i][1]=0; for (int i=head[x];i;i=next[i]) if (!vis[list[i]]) { sum=size[list[i]]; if (size[list[i]]>size[x]) size[list[i]]=nowsum-size[x]; root=0; if (sum>=K) getroot(list[i]); work(root,size[list[i]]); } } int main() { n=read(); m=read(); K=read()-1; for (int i=1;i<=m;i++) { int u=read(),v=read(),w=read(); a[u].push_back(make_pair(v,w)); a[v].push_back(make_pair(u,w)); } for (int i=1;i<=n;i++) { sort(a[i].begin(),a[i].end()); for (int j=a[i].size()-1;~j;j--) insert_(i,a[i][j].first,a[i][j].second); } dijkstra(); memset(vis,0,sizeof(vis)); cnt=0; dfs(1); root=0; fm[root]=inf; sum=n; memset(vis,0,sizeof(vis)); getroot(1); work(root,sum); printf("%d %d\n",ans1,ans2); return 0; }
相关文章推荐
- LeetCode Sqrt(x)
- SQL中 patindex函数的用法
- node环境搭建安装nmp
- fopen,fopen_s,_wfopen_s与_fsopen, _wfsopen的区分
- apache2.4.18中启用h2c
- jquery全局ajax参数详细执行分析-$.ajax竟然可以这样用!
- 开始学习node.js了,第一节,fs文件系统 【fs.rename】重命名文件/文件夹
- 使用XML文件输入和输出和YAML文件 目标 你会发现以下问题的答案: 如何打印和阅读文本条目文件和OpenCV使用YAML或XML文件? 如何为OpenCV做同样的数据结构?
- 平凡之路--读《异类》
- 面试题一:linux面试题
- 【bzoj1101】[POI2007]Zap 莫比乌斯反演
- Spark on Hadoop Yarn 部署
- php分享十五:php的命令行操作
- 查询系统负载信息 Linux 命令详解
- hdu 3810 Magina 5亿的背包,队列优化DP
- 四大组件---service生命周期事例详解(二)
- hdoj2049不容易系列之(4)——考新郎
- Jquery $.ajax请求详解及ajax全局变量分析
- UILabel和NSAttributedString那些事
- 【Android测试】【第二节】性能——CPU时间片