【hdu3238】Finding the Most Vital Node of a Shortest Path
来源:互联网 发布:2016年中日贸易数据 编辑:程序博客网 时间:2024/05/30 04:17
题意:给定s,t,求出无向图上,去掉第i个点之后的最短路径极其路径条数,每个i都要计算出来。
出个论文题就算了,还非要算方案...
先求出最短路树,考虑去掉节点i,我们可以分出三层,一层节点集合是节点i的子树外的节点,称为U,一层是节点i的若干子树但去除包括汇点的子树,称为O,一层是汇点所在的i的一棵子树,称为D;那么如果去掉i节点,最短路的构成有两种,一种是经过U的若干节点跨过一条边到D再经过若干节点到t,另一种是经过U的若干节点再经过O的若干节点再经过若干D的节点到t。
观察这两种路径,在U和D里面的最短距离一遍预处理就出来,而在O中的却比较麻烦,因为要算出不经过i的在O中的最短路,因此必须用到最短路树的性质。
首先通过观察,可以发现几个性质:如果按从s-t的顺序访问spt的每个点i,那么其余点会依次从D->O->U,也就是说,每个点只会属于某一个i的O集合,而在其他情况要么是D要么是U,因此就可以依次预处理每一个点i的Oi而互不影响,具体就是通过Ui->Oi的边做出Oi中点的初值,然后再在Oi的内部做迪杰斯特拉,在内部更新,而Di明显不会影响。
接下来是通过s到所有点的距离,所有点到t的距离以及每个点在其属于的Oi集合不经过其i到s的距离更新答案,具体来说就是还是依次按s-t的顺序做,依次递推出i的答案。
用个map维护一下到t的若干路径长度与方案,现在已经处理了rt[i],对于i点来说其Oi中的点将从Di变过来,而以前可能用U->D的路径更新过,因此要先删掉这些路径,而他又由D变成了新的O,因此要再用其O->D来加上一些最短路径,处理完这些后,点i的答案就可以算出来了,然后再把Oi中的点变为U,删掉其Oi->D的路径,添入一些U->D的路径。
然后这个题除了要求最短路还有求方案就更麻烦,首先是求O中的最短路的时候,除了要继承U的最短路,还要继承其方案,然后是因为如果是任意的最短路树的话可能存在D->U的路径,而这种路径会经过i,导致在算i的答案的时候计算了一条D->U->D的不合法路径,譬如数据:
4 5 3 4 X
3 2 3
3 1 6
2 1 5
2 4 2
4 1 1
解决方案是从t往s建树,每次把最短路图上的没被访问过的点给扯到他的子树中来,这样就可以避免有D->U的路径。
如果一个点不在我们默认的最短路径上,它有可能影响方案数,此时只需减掉经过它的方案数即可。
还有一个坑的地方,我的处理方法每次要减掉一些数,而这个奇怪的输出要取模,这就导致每次我不知道减去之后是真为0还是模为0...但这数据还是让我过了
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <map>#include <utility>const int oo=1073741819,mo=19880830;using namespace std;vector <int> stack;map < int , long long > Map;int next[2000000],sora[2000000],cost[2000000],st[500000],u[500000],tail[500000],b[2000000];int v[500000],col[500000],d[500000],rt[3][500000];int ss,n,m,m1,s,t,q;struct dist{int m;long long c;}D[3][500000],ans[500000];void origin(){ ss=n; for (int i=1;i<=n;i++) tail[i]=i,next[i]=0; for (m1=1;m1<=n+2;m1<<=1) ; for (int i=1;i<=m1+m1;i++) b[i]=0; for (int i=1;i<=n;i++) b[i+m1]=i,d[i]=oo; for (int i=1;i<=n;i++) { v[i]=col[i]=0; for (int j=0;j<=2;j++) D[j][i].m=oo,D[j][i].c=0,rt[j][i]=0; ans[i].m=oo,ans[i].c=0; } Map.clear(),stack.clear();}void link(int x,int y,int z){++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,cost[ss]=z,next[ss]=0;++ss,next[tail[y]]=ss,tail[y]=ss,sora[ss]=x,cost[ss]=z,next[ss]=0;}int mind(int x,int y){ return (d[x]<d[y]) ? x : y;}void change(int x,int w){ d[x]=w; for (x=((x+m1)>>1);x;x>>=1) b[x]=mind(b[x<<1],b[(x<<1)+1]);}void dij(int e,int &r){ for (;d[b[1]]!=oo;) { int x=b[1],cos=d[x]; st[++r]=x,D[e][x].m=cos; change(x,oo); for (int i=x,ne;next[i];) { i=next[i],ne=sora[i]; if (d[ne]!=oo && cos+cost[i]<d[ne] && v[x]==v[ne]) { rt[e][ne]=x; change(ne,cos+cost[i]); } } }}void spfa(int s,int e){ for (int i=0;i<=n;i++) change(i,oo+1); change(s,0); int r=0; dij(e,r); D[e][st[1]].c=1; for (int i=1;i<=r;i++) { int x=st[i]; for (int i=x,ne;next[i];) { i=next[i],ne=sora[i]; if (D[e][x].m+cost[i]==D[e][ne].m) (D[e][ne].c+=D[e][x].c)%=mo; } }}void dfs(int x,int level){stack.push_back(x);v[x]=level;for (int i=x,ne;next[i];) {i=next[i],ne=sora[i];if (D[0][x].m+cost[i]==D[0][ne].m && !v[ne] && !col[ne]) dfs(ne,level);}}bool cmp(int i,int j){if (v[i]!=v[j]) return v[i]>v[j];return col[i]<col[j];}void updata(int w,long long c){map < int , long long > :: iterator it=Map.find(w);if (it==Map.end()) {Map[w]=c;return ;}it->second=((it->second+c)%mo+mo)%mo;if (!(it->second)) Map.erase(it);}void add_o_d(int x,int e){for (int i=x,ne;next[i];) { i=next[i],ne=sora[i]; if (v[ne]<v[x]) { int cos=D[2][x].m+cost[i]+D[1][ne].m; long long tmp=(D[2][x].c*D[1][ne].c)%mo; if (!tmp) return ; updata(cos,tmp*e); } }}void add_u_d(int x,int e){for (int i=x,ne;next[i];) { i=next[i],ne=sora[i]; if (e*v[ne]>e*v[x]) { int cos; long long tmp; if (e==1) { cos=D[0][ne].m+cost[i]+D[1][x].m; tmp=(D[0][ne].c*D[1][x].c)%mo; } else { cos=D[0][x].m+cost[i]+D[1][ne].m; tmp=(D[0][x].c*D[1][ne].c)%mo; } if (!tmp) return ; updata(cos,-tmp*e); } }}int main(){ for (int test=1;scanf("%d%d%d%d%d",&n,&m,&s,&t,&q)==5;test++) { if (!n && !m && !s && !t && !q) break; origin(); for (int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); link(x,y,z); } spfa(s,0); spfa(t,1); for (int i=t;i;i=rt[0][i]) col[i]=1; for (int i=t,cnt=1;i;i=rt[0][i],++cnt) { stack.clear(); dfs(i,cnt); for (int i=1;i<(int)stack.size();i++) { int x=stack[i]; d[x]=oo+1; for (int i=x,ne;next[i];) { i=next[i],ne=sora[i]; if (!v[ne] && D[0][ne].m+cost[i]<d[x]) change(x,D[0][ne].m+cost[i]); } } int r=0; dij(2,r); for (int i=1;i<=r;i++) { int x=st[i]; for (int i=x,ne;next[i];) { i=next[i],ne=sora[i]; if (!v[ne]) { if (D[0][ne].m+cost[i]==D[2][x].m) (D[2][x].c+=D[0][ne].c)%=mo; } } for (int i=x,ne;next[i];) { i=next[i],ne=sora[i]; if (v[ne]==v[x] && !col[ne]) { if (D[2][x].m+cost[i]==D[2][ne].m) (D[2][ne].c+=D[2][x].c)%=mo; } } } } for (int i=1;i<=n;i++) u[i]=i; sort(u+1,u+n+1,cmp); for (int i=1;i<=n;i++) { int x=u[i]; add_u_d(x,1); if (!col[x]) { add_o_d(x,1); } else { if (Map.empty()) ans[x].m=oo,ans[x].c=0; else { map < int , long long > :: iterator it; it=Map.begin(); if (it!=Map.end()) ans[x].m=it->first,ans[x].c=it->second; } for (int j=i-1;j>=1 && v[u[j]]==v[u[i]];j--) add_o_d(u[j],-1); for (int j=i;j>=1 && v[u[j]]==v[u[i]];j--) add_u_d(u[j],-1); } } printf("Case %d:",test); for (int i=1;i<=q;i++) { int x; scanf("%d",&x); long long Ans=0,X=1; for (int j=1;j<=n;j++) { if (ans[j].m==oo) { if (col[j]) ans[j].m=0,ans[j].c=0; else { ans[j].m=D[0][t].m,ans[j].c=D[0][t].c; int x=j; for (int i=x,ne;next[i];) { i=next[i],ne=sora[i]; if (D[0][x].m+cost[i]+D[1][ne].m==D[0][t].m) ans[j].c=((ans[j].c-D[0][x].c*D[1][ne].c)%mo+mo)%mo; } if (ans[j].m==oo) ans[j].m=0,ans[j].c=0; } } Ans=(Ans+X*ans[j].m)%mo; X=(X*x)%mo; Ans=(Ans+ans[j].c*X)%mo; X=(X*x)%mo; } printf(" %lld",Ans); } printf("\n\n"); } return 0;}
- 【hdu3238】Finding the Most Vital Node of a Shortest Path
- A - Shortest path of the king
- A. Shortest path of the king
- A. Shortest path of the king
- 3A - Shortest path of the king
- CF 3A Shortest path of the king
- Shortest path of the king(比赛2.A)
- coderforce 3A-Shortest path of the king
- codeforces 3A - Shortest path of the king
- Codeforces 3A Shortest path of the king BFS
- code forces 3A Shortest path of the king
- codeforces 3A Shortest path of the king
- 【pair_简单贪心】#3 A. Shortest path of the king
- Codeforces 3A Shortest Path of the King
- Codeforces Round #3A. Shortest path of the king
- Codeforces Beta Round #3 A. Shortest path of the king
- Codefoeces 3A. Shortest path of the king
- Codeforces 3A. Shortest path of the king(贪心:暴力)
- 00_自制51单片机开发板开发日志
- 此博客不再更新,已转私人博客,欢迎收录
- 递归第一次
- UVA10879H Code Refactoring
- 二分查找
- 【hdu3238】Finding the Most Vital Node of a Shortest Path
- ubuntu下使用vsftpd搭建ftp服务器
- 自定义toggle button
- uva 11090 Going in Cycle!!
- java 学习笔记 栈内存与堆内存
- 3n+1问题
- PendingIntent与Intent的区别
- tomcat6.0无法解压war包
- iOS -- OpenSSL生成RSA双密匙+签名证书(流程)