【题解】
先建反向图,然后跑拓扑排序求出最长路。
将所有的点按照最长路从小到大分层,把上一层连向这一层的边按照边权为第一关键字、起点的排名为第二关键字排序。
按照这个顺序更新这一层的答案,按照这一层每个点被更新的顺序得到这一层的点的排名。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define LL long long 5 #define rg register 6 #define N 1000010 7 #define Mod (998244353) 8 using namespace std; 9 int n,m,tot,cnt,last[N],in[N],dis[N],q[N],rk[N],ans[N]; 10 struct edge{int to,pre,dis;}e[N]; 11 struct poi{int dis,num;}p[N]; 12 struct rec{int w,rk,from,to;}r[N]; 13 inline int read(){ 14 int k=0,f=1; char c=getchar(); 15 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 16 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 17 return k*f; 18 } 19 inline bool cmp(rec a,rec b){ 20 if(a.w==b.w) return a.rk<b.rk; 21 return a.w<b.w; 22 } 23 inline bool cmp2(poi a,poi b){return a.dis<b.dis;} 24 inline void topu(int x){ 25 int front=0,rear=1; q[1]=x; 26 while(front<rear){ 27 int now=q[++front]; 28 for(rg int i=last[now],to;i;i=e[i].pre){ 29 to=e[i].to; 30 dis[to]=max(dis[to],dis[now]+1); 31 if(!(--in[to])) q[++rear]=to; 32 } 33 } 34 } 35 int main(){ 36 n=read(); m=read(); 37 for(rg int i=1;i<=m;i++){ 38 int u=read(),v=read(),d=read(); in[u]++; 39 e[++tot]=(edge){u,last[v],d}; last[v]=tot; 40 } 41 for(rg int i=1;i<=n;i++)if(!in[i]&&!dis[i]) topu(i); 42 for(rg int i=1;i<=n;i++){ 43 p[i].num=i; 44 if(in[i]) p[i].dis=2e9; else p[i].dis=dis[i]; 45 } 46 sort(p+1,p+1+n,cmp2); 47 int st=1,ed=1; 48 while(st<=n){ 49 tot=0; 50 while(p[ed].dis==p[st].dis&&ed<=n){ 51 int now=p[ed].num; 52 // printf("now=%d ed=%d ",now,ed); 53 for(rg int i=last[now],to;i;i=e[i].pre){ 54 if(dis[to=e[i].to]==dis[now]+1) r[++tot]=(rec){e[i].dis,rk[now],now,to}; 55 } 56 ed++; 57 } 58 sort(r+1,r+1+tot,cmp); 59 for(rg int i=1;i<=tot;i++)if(!ans[r[i].to]){ 60 // printf("%d %d %d %d %d ",r[i].to,r[i].from,r[i].w,ans[r[i].from],ans[r[i].to]); 61 ans[r[i].to]=(1ll*ans[r[i].from]*29+r[i].w*29)%Mod; 62 rk[r[i].to]=++cnt; 63 } 64 st=ed; 65 } 66 for(rg int i=1;i<=n;i++) if(in[i]>0) puts("Infinity"); else printf("%d ",ans[i]%Mod); 67 return 0; 68 }