BZOJ2750: [HAOI2012]Road

时间:2023-03-08 18:44:44
BZOJ2750: [HAOI2012]Road

2750: [HAOI2012]Road

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 261  Solved: 113
[Submit][Status]

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

Sample Output

2
3
2
1

HINT

数据规模

30%的数据满足:n≤15、m≤30

60%的数据满足:n≤300、m≤1000

100%的数据满足:n≤1500、m≤5000、w≤10000

Source

题解:

60分是社交网络。。。居然还有升级版。。。考场上果断写60分暴力。。

yy了一两天结果发现题看错了。。。

以为是经过某个点的最短路的数目,果断写了topsort+dfs。。。简直不能再sb。。。

贴上我的sb代码

 #include<cstdio>

 #include<cstdlib>

 #include<cmath>

 #include<cstring>

 #include<algorithm>

 #include<iostream>

 #include<vector>

 #include<map>

 #include<set>

 #include<queue>

 #include<string>

 #define inf 1000000000

 #define maxn 500+100

 #define maxm 500+100

 #define eps 1e-10

 #define ll long long

 #define pa pair<int,int>

 #define for0(i,n) for(int i=0;i<=(n);i++)

 #define for1(i,n) for(int i=1;i<=(n);i++)

 #define for2(i,x,y) for(int i=(x);i<=(y);i++)

 #define for3(i,x,y) for(int i=(x);i>=(y);i--)

 #define mod 1000000007

 using namespace std;

 inline int read()

 {

     int 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 go,next,w;}e[*maxm],e2[*maxm]; ll n,m,k,s,t,tot,q[maxn],d[maxn],head[maxn],head2[maxn],f[maxn],g[maxn],ans[maxn],inp[maxn];
bool v[maxn];
inline void insert(int x,int y,int z)
{
e[++tot].go=y;e[tot].next=head[x];head[x]=tot;e[tot].w=z;
}
inline void insert2(int x,int y)
{
e2[++tot].go=y;e2[tot].next=head2[x];head2[x]=tot;
}
inline void add(ll &x,ll &y)
{
x+=y;
if(x>=mod)x%=mod;
}
void dfs(int x)
{
g[x]=f[x];
for(int i=head2[x];i;i=e2[i].next){dfs(e2[i].go);add(g[x],g[e2[i].go]);};
} void work(int s) { for(int i=;i<=n;++i) d[i]=inf; memset(v,,sizeof(v)); int l=,r=,x,y;q[]=s;d[s]=; while(l!=r) { x=q[++l];if(l==maxn)l=;v[x]=; for(int i=head[x];i;i=e[i].next) if(d[x]+e[i].w<d[y=e[i].go]) { d[y]=d[x]+e[i].w; if(!v[y]){v[y]=;q[++r]=y;if(r==maxn)r=;} } }
memset(head2,,sizeof(head2));tot=;
memset(inp,,sizeof(inp));
memset(f,,sizeof(f));
memset(g,,sizeof(g));
for1(x,n)
for(int i=head[x],y;i;i=e[i].next)
if(d[x]+e[i].w==d[y=e[i].go])insert2(x,y),inp[y]++;
l=;q[r=]=s;f[s]=;
while(l<r)
{
int x=q[++l];
for(int i=head2[x],y;i;i=e2[i].next)
{
inp[y=e2[i].go]--;
add(f[y],f[x]);
if(!inp[y])q[++r]=y;
}
}
dfs(s);
for1(i,n)add(ans[i],g[i]);ans[s]--;
for1(i,n)cout<<i<<' '<<g[i]<<' '<<f[i]<<endl;
cout<<"TTTTTTTTTTT"<<endl;
} int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); n=read();m=read();int x,y,z;
for1(i,m)x=read(),y=read(),z=read(),insert(x,y,z);
for1(i,n)work(i);
for1(i,n)printf("%lld\n",ans[i]); return ; }

纠正题意之后突然发现不会做了 QAQ。。。

膜拜了lyd的代码才知道,居然这么神。。。

dijkstra算法可以在算出最短路的同时将点的源点的距离排序,然后按照这个

从前往后枚举在最短路上的边可以得到源点到每个点的最短路的数目,记为a[i]  (也就是我的topsort)

从后往前枚举在最短路上的边可以得到经过每个点有多少条最短路,记为b[i]  (也就是我的dfs,我好像写错了23333)

然后对于每条边就是 +=a[e[i].from]*b[e[i].go]
图论题的技巧还有很多,我还太年轻23333

代码:

 #include<cstdio>

 #include<cstdlib>

 #include<cmath>

 #include<cstring>

 #include<algorithm>

 #include<iostream>

 #include<vector>

 #include<map>

 #include<set>

 #include<queue>

 #include<string>

 #define inf 1000000000

 #define maxn 20000

 #define maxm 50000

 #define eps 1e-10

 #define ll long long

 #define pa pair<int,int>

 #define for0(i,n) for(int i=0;i<=(n);i++)

 #define for1(i,n) for(int i=1;i<=(n);i++)

 #define for2(i,x,y) for(int i=(x);i<=(y);i++)

 #define for3(i,x,y) for(int i=(x);i>=(y);i--)

 #define mod 1000000007

 using namespace std;

 inline int read()

 {

     int 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 go,next,w;}e[*maxm],e2[*maxm]; ll n,m,k,s,t,tot,q[maxn],d[maxn],head[maxn],a[maxn],b[maxn],c[maxn],ans[maxn];
bool v[maxn];
inline void insert(int x,int y,int z)
{
e[++tot].go=y;e[tot].next=head[x];head[x]=tot;e[tot].w=z;
}
inline void add(ll &x,ll y)
{
x+=y;
if(x>=mod)x%=mod;
} void dijkstra(int s) { priority_queue<pa,vector<pa>,greater<pa> >q; for(int i=;i<=n;i++)d[i]=inf; memset(v,,sizeof(v)); d[s]=;q.push(make_pair(,s));
int t=; while(!q.empty()) { int x=q.top().second;q.pop(); if(v[x])continue;v[x]=;c[++t]=x; for(int i=head[x],y;i;i=e[i].next) if(d[x]+e[i].w<d[y=e[i].go]) { d[y]=d[x]+e[i].w; q.push(make_pair(d[y],y)); } }
memset(a,,sizeof(a));a[s]=;
memset(b,,sizeof(b));
for1(i,t)b[c[i]]=;
for1(i,t)
for(int j=head[c[i]],y;j;j=e[j].next)
if(d[c[i]]+e[j].w==d[y=e[j].go])add(a[y],a[c[i]]);
for3(i,t,)
for(int j=head[c[i]],y;j;j=e[j].next)
if(d[c[i]]+e[j].w==d[y=e[j].go])add(b[c[i]],b[y]);
for1(i,n)
for(int j=head[i],y;j;j=e[j].next)
if(d[i]+e[j].w==d[y=e[j].go])add(ans[j],a[i]*b[y]);
} int main() { freopen("roadsw.in","r",stdin); freopen("roadsw.out","w",stdout); n=read();m=read();int x,y,z;
for1(i,m)x=read(),y=read(),z=read(),insert(x,y,z);
for1(i,n)dijkstra(i);
for1(i,m)printf("%lld\n",ans[i]); return ; }