最短路+拓扑序DP
orz zyf & lyd
统计每条边在多少条最短路径上……其实可以统计 有多少条最短路径经过了x,以及y出发到达任意一个结束点有多少种走法(沿最短路)
我们可以用Dijkstra求出以 i 为起点的最短路径图,它是一个DAG,然后我们用dij扩展的顺序(一个拓扑序)来搞DP!
令a[x]表示从 i 沿最短路走到 x 的方案数,b[x]表示从 x 往出走,沿最短路走到任意一个结束结点的总方案(就是经过x的最短路条数?只不过只看后半段)
其实就是将最短路分开两半进行统计了……然后乘一下……
通过这题的思路可以搞CTSC2015 Day1 T1?
跪了,pq应该把<定义为a.d>b.d……唉真是傻逼了
1 /************************************************************** 2 Problem: 2750 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:2276 ms 7 Memory:1388 kb 8 ****************************************************************/ 9 10 //BZOJ 2750 11 #include<queue> 12 #include<vector> 13 #include<cstdio> 14 #include<cstring> 15 #include<cstdlib> 16 #include<iostream> 17 #include<algorithm> 18 #define rep(i,n) for(int i=0;i<n;++i) 19 #define F(i,j,n) for(int i=j;i<=n;++i) 20 #define D(i,j,n) for(int i=j;i>=n;--i) 21 #define pb push_back 22 using namespace std; 23 inline int getint(){ 24 int v=0,sign=1; char ch=getchar(); 25 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 26 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 27 return v*sign; 28 } 29 const int N=1510,M=5010,INF=~0u>>2; 30 const int P=1000000007; 31 typedef long long LL; 32 /******************tamplate*********************/ 33 int to[M],next[M],len[M],head[N],cnt; 34 void add(int x,int y,int z){ 35 to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; len[cnt]=z; 36 } 37 struct node{ 38 int x,d; 39 bool operator < (const node &b)const{ return d>b.d;} 40 }; 41 int n,m,v[N],a[N],b[N],c[N],d[N]; 42 priority_queue<node>Q; 43 int ans[M]; 44 void dijkstra(int S){ 45 memset(d,0x3f,sizeof d); 46 memset(v,0,sizeof v); 47 d[S]=0; 48 int t=0; 49 Q.push((node){S,0}); 50 while(!Q.empty()){ 51 int x=Q.top().x; Q.pop(); 52 if (v[x]) continue; 53 v[x]=++t; 54 for(int i=head[x];i;i=next[i]){ 55 int y=to[i],l=len[i]; 56 if (d[y]>d[x]+l){ 57 d[y]=d[x]+l; 58 Q.push((node){y,d[y]}); 59 } 60 } 61 } 62 F(i,1,n) if (v[i]) c[v[i]]=i; 63 memset(a,0,sizeof a); a[c[1]]=1; 64 F(i,1,n) b[i]=1; 65 F(x,1,t) 66 for(int i=head[c[x]];i;i=next[i]) 67 if (d[to[i]]==d[c[x]]+len[i]) 68 a[to[i]]=(a[to[i]]+a[c[x]])%P; 69 D(x,t,1) 70 for(int i=head[c[x]];i;i=next[i]) 71 if (d[to[i]]==d[c[x]]+len[i]) 72 b[c[x]]=(b[c[x]]+b[to[i]])%P; 73 F(x,1,n) 74 for(int i=head[x];i;i=next[i]) 75 if (d[to[i]]==d[x]+len[i]) 76 ans[i]=(ans[i]+(LL)a[x]*b[to[i]]%P)%P; 77 } 78 int main(){ 79 #ifndef ONLINE_JUDGE 80 freopen("2750.in","r",stdin); 81 freopen("2750.out","w",stdout); 82 #endif 83 n=getint(); m=getint(); 84 F(i,1,m){ 85 int x=getint(),y=getint(),z=getint(); 86 add(x,y,z); 87 } 88 F(i,1,n) dijkstra(i); 89 F(i,1,m) printf("%d ",ans[i]); 90 return 0; 91 }
2750: [HAOI2012]Road
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 347 Solved: 155
[Submit][Status][Discuss]
Description
C
国有n座城市,城市之间通过m条单向道路连接。一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且
仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路。现在,这个任务交给了你。
Input
第一行包含两个正整数n、m
接下来m行每行包含三个正整数u、v、w,表示有一条从u到v长度为w的道路
Output
输出应有m行,第i行包含一个数,代表经过第i条道路的最短路的数目对1000000007取模后的结果
Sample Input
4 4
1 2 5
2 3 5
3 4 5
1 4 8
1 2 5
2 3 5
3 4 5
1 4 8
Sample Output
2
3
2
1
3
2
1
HINT
数据规模
30%的数据满足:n≤15、m≤30
60%的数据满足:n≤300、m≤1000
100%的数据满足:n≤1500、m≤5000、w≤10000