B. Wycieczki
题目描述
输入格式
输出格式
样例
数据范围与提示
这道题时间跨度比较长了,主要是因为这道题贼难调,稍有不慎就会WA,而且这道题的测试点贼多,多到会出现2分情况,所以真的是我的签名说的,一杯茶一包纸,一份代码调成X
其实这道题还算好像,而且有思维量,主要就是要把边的矩阵拆点,然后建边,注意需点,也就是整个矩阵会扩大三倍;整个题其实就是二分(我打了一半,跑的实在是太慢了,所以换了一种方法)倍增,倍增就和求lca其实是一样的,就是换成了矩阵,不知其他神犇是怎么打的,反正我是使用结构体,但是要注意细节,整个卡了一晚上,就是因为矩阵传参没加取地址,加上就A了,有神犇知道为啥的就留言吧
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> using namespace std; #define LL long long #define re register #define F(i,a,b) for(LL i=a;i<=b;i++) LL n,m,u,v,d,t; long long s,k; bool flag; inline LL read() { re LL ss=0;char bb=getchar(); while(bb<48||bb>57)bb=getchar(); while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar(); return ss; } struct Martix { LL x[250][250]; void init() { memset(x,0,sizeof(x)); } }mul[125],tmp; Martix bg,base,now; void made(Martix &a,Martix &b,Martix &c) { flag=1; tmp.init(); F(i,1,3*n+1) F(l,1,3*n+1) { if(!a.x[i][l])continue; //debug(i);debug(l); F(j,1,3*n+1) tmp.x[i][j]=tmp.x[i][j]+a.x[i][l]*b.x[l][j]; if(i==1&&tmp.x[i][3*n+1]>=k)flag=0; } c=tmp; } int main() { //freopen("cnm.txt","r",stdin); n=read(),m=read(),k=read(); F(i,1,n) { bg.x[1][i]=1; base.x[i][i+n]=1; base.x[i+n][i+2*n]=1; } while(m--) { u=read(),v=read(),d=read(); base.x[u+(d-1)*n][v]++; base.x[u+(d-1)*n][3*n+1]++; } base.x[3*n+1][3*n+1]=1; mul[0]=base; for(;t<=63;t++) { if(t) made(mul[t-1],mul[t-1],mul[t]); made(bg,mul[t],now); if(!flag||now.x[1][3*n+1]>=k){break;} } t--; if(t==63&&now.x[1][3*n+1]<k) { puts("-1"); return 0; } for(LL i=t;i>=0;i--) { made(bg,mul[i],now); if(flag&&now.x[1][3*n+1]<k) { s+=(1ll<<i); bg=now; } } printf("%lld ",s+1); }
endl;