版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41709770/article/details/88584696
怎么又是些毒瘤题
确实被恶心到了
jzoj 6059 Tried
https://jzoj.net/senior/#main/show/6059
其实就是找最长路径,但是细节简直多到吐
搞得我自己打的dp,每个子任务都错一个,结果又是0分QAQ
但是用topsort+逐层贪心好像避免了很多特判
题解大法好
题解:
若图中存在一条非 0 边可以到达任意一个环,我们可以直接输出
两个 inf,否则我们可以将 0 环给缩成一个点,方案数记为 inf。
于是只要考虑图是一个有向无环图时的情况。
接下来我们可以求出每个点向下得到的最大位数,随后逐位确定
即可,。
多说无益,直接上浓缩了精力与心血的代码
QAQ
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int MAXN=1e5+5;
const int MAXM=1e6+5;
const int mod=998244353;
int n,m;
struct grath{
int head[MAXN],next[MAXM*2],to[MAXM*2],w[MAXM*2],du[MAXN],cnt;
int ml[MAXN][2],f[MAXN];
bool p[MAXN];
void add(int u,int v,int l){
next[++cnt]=head[u],to[cnt]=v,w[cnt]=l,du[v]++,head[u]=cnt;
}
}A,B,C;
int dfn[MAXN],low[MAXN],tot,stack[MAXN],top,isn[MAXN];
int h[MAXN],sh,w[MAXN];
int mx,sum;
void tarjan(int x){
dfn[x]=low[x]=++tot,stack[++top]=x,isn[x]=1;
for(int i=A.head[x];i;i=A.next[i]){
int y=A.to[i];
if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if(isn[y]) low[x]=min(low[x],dfn[y]);
}
if(dfn[x]==low[x]){
sh++;
while(1){
int t=stack[top--];
h[t]=sh,isn[t]=0;
if(t==x) break;
}
}
}
int Plus(int x,int y){
if(x<0||y<0) return -1;
return (x+y)%mod;
}
queue<int>q;
void topsort(grath &A){
for(int i=1;i<=sh;i++){
if(!A.du[i]) q.push(i);
A.f[i]= w[i]>=0?-1:1;
}
while(!q.empty()){
int x=q.front();q.pop();
for(int i=A.head[x];i;i=A.next[i]){
int y=A.to[i],w=A.w[i]; A.du[y]--;
if(!A.du[y]) q.push(y);
A.p[y]|=A.p[x];
A.ml[y][w>0]=max(A.ml[y][w>0],max(A.ml[x][0],A.ml[x][1])+1);
A.f[y]=Plus(A.f[x],A.f[y]);
}
}
}
vector<int>t[MAXN];
bool isv[MAXN];
int main(){
freopen("tried.in","r",stdin);
freopen("tried.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,l;scanf("%d%d%d",&u,&v,&l);
A.add(u,v,l);
}
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
memset(w,-1,sizeof(w));
for(int x=1;x<=n;x++) for(int i=A.head[x];i;i=A.next[i]){
int y=A.to[i],l=A.w[i];
if(h[x]!=h[y]) B.add(h[x],h[y],l),C.add(h[y],h[x],l);
else w[h[x]]=max(w[h[x]],l);
}
for(int i=1;i<=sh;i++) if(w[i]>0) {printf("inf\ninf");return 0;}
for(int i=1;i<=sh;i++) if(w[i]==0) B.p[i]=C.p[i]=1;
topsort(B);
for(int x=1;x<=sh;x++)
if(B.p[x]) for(int i=B.head[x];i;i=B.next[i])
if(B.w[i]) {printf("inf\ninf");return 0;}
topsort(C);
for(int i=1;i<=sh;i++) mx=max(mx,B.ml[i][1]);
if(!mx){
for(int i=1;i<=sh;i++) sum=Plus(sum,C.f[i]);
printf("0\n");
if(sum<0) printf("inf");
else printf("%d",sum);
return 0;
}
for(int i=1;i<=sh;i++)
if(B.ml[i][1]==mx) t[mx].push_back(i),isv[i]=1;
else{
int o=max(B.ml[i][0],B.ml[i][1]);
if(o<mx) t[o].push_back(i);
C.f[i]=0;
}
for(int k=mx;k;k--){
int o=0;
for(int j=0;j<t[k].size();j++){
int x=t[k][j];
if(!isv[x]) continue;
for(int i=C.head[x];i;i=C.next[i]){
int y=C.to[i];
if(max(B.ml[y][0],B.ml[y][1])==k-1) o=max(o,C.w[i]);
}
}
for(int j=0;j<t[k].size();j++){
int x=t[k][j];
if(!isv[x]) continue;
for(int i=C.head[x];i;i=C.next[i]){
int y=C.to[i];
if(max(B.ml[y][0],B.ml[y][1])==k-1&&o==C.w[i]) C.f[y]=Plus(C.f[y],C.f[x]),isv[y]=1;
}
}
printf("%d",o);
}
printf("\n");
for(int i=0;i<t[0].size();i++) if(isv[t[0][i]]) sum=Plus(sum,C.f[t[0][i]]);
if(sum<0) printf("inf");
else printf("%d",sum);
return 0;
}
第二题又是神奇操作:话说是怎么又把四个
变成四元环的。
第三题好像还能搞。