牛客网NOIP赛前集训营 第6场 T1 最长路

【题解】

  先建反向图,然后跑拓扑排序求出最长路。

  将所有的点按照最长路从小到大分层,把上一层连向这一层的边按照边权为第一关键字、起点的排名为第二关键字排序。

  按照这个顺序更新这一层的答案,按照这一层每个点被更新的顺序得到这一层的点的排名。

 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\n",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\n",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\n",ans[i]%Mod);
67     return 0;
68 }

 

posted @ 2018-10-23 10:39  Driver_Lao  阅读(150)  评论(0编辑  收藏  举报