题目描述
输入输出格式
输入格式:
输出格式:
输入输出样例
Solution:
常规(水)题,考试的时候细节写挂。
首先以$2$为源点处理出到其他点的最短路,然后遍历一遍图,标记那些不满足$dis[u]>dis[v]$的边,最后只要从$1$广搜一下处理出答案就好了,广搜时记录一下所到边的变化值,用变化值去更新答案。
代码:
#include<bits/stdc++.h> #define il inline #define ll long long #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) using namespace std; const int N=100005; int n,m,to[N],net[N],w[N],dis[N],h[N],cnt; int ans[N],deta[N]; bool vis[N],ct[N]; il int gi(){ int a=0;char x=getchar();bool f=0; while((x<'0'||x>'9')&&x!='-')x=getchar(); if(x=='-')x=getchar(),f=1; while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar(); return f?-a:a; } il void add(int u,int v,int c){to[++cnt]=v,net[cnt]=h[u],h[u]=cnt,w[cnt]=c;} queue<int>q; il void pre(){ memset(dis,0x3f,sizeof(dis)); memset(ct,0,sizeof(ct)); dis[2]=0;q.push(2); while(!q.empty()){ int u=q.front();q.pop();vis[u]=0; for(int i=h[u];i;i=net[i]) if(dis[to[i]]>dis[u]+w[i]){ dis[to[i]]=dis[u]+w[i]; if(!vis[to[i]])vis[to[i]]=1,q.push(to[i]); } } For(u,1,n) for(int i=h[u];i;i=net[i]) if(dis[u]<=dis[to[i]]) ct[i]=1; } il void solve(){ memset(ans,0,sizeof(ans)); ans[1]=1;deta[1]=1; q.push(1); while(!q.empty()){ int u=q.front();vis[u]=0;q.pop(); for(int i=h[u];i;i=net[i]) if(!ct[i]){ deta[to[i]]+=deta[u], ans[to[i]]+=deta[u]; if(!vis[to[i]]) vis[to[i]]=1,q.push(to[i]); } deta[u]=0; } printf("%d ",ans[2]); } int main(){ int u,v,c; while(scanf("%d",&n)==1){ if(!n)break; m=gi(); cnt=0; memset(h,0,sizeof(h)); For(i,1,m) u=gi(),v=gi(),c=gi(),add(u,v,c),add(v,u,c); pre(),solve(); } return 0; }