題目
給定一張有向圖(可能有自環,保證沒有相同類型的重邊),每條邊有兩種類型,分別爲1或者0 從1開始走,要求走過的路徑類型成如下方式
0
01
0110
01101001
第 個是由第 個和第 個取反拼在後面, 求最長路。
如果最長路長度大於 輸出
思路
我們定義
表示是否存在 到 的長度爲 的如題目所述的路徑( 爲取反路徑)
然後我們知道,如果將這個狀態後面兩維表示成鄰接矩陣,可以用矩乘來轉移,有
然後有一個套路
for(int i=1;i<=A.r;i++)
for(int j=1;j<=B.c;j++)
for(int k=1;k<=A.c;k++)
C[i][j]+=A[i][k]*B[k][j];
我們知道是個矩乘都是這樣寫的
但是這裏鄰接矩陣我們還可以這樣寫
for(int i=1;i<=A.r;i++)
for(int k=1;k<=A.c;k++)
if(A[i][k])
C[i]|=B[k];
這裏 均爲 它的含義也非常直觀不講了
然後倍增跑跑就行了
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<bitset>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define ULL unsigned long long
using namespace std;
int read(){
int x=0,y=0;char c=getchar();
while(c<'0'||'9'<c) c=getchar();
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x;
}
#define Log 61
#define MAXN 500
#define INF 0x3f3f3f3f
int n,m;
struct Matrix{
int r,c;
bitset<MAXN> a[MAXN+5];
bitset<MAXN>& operator [] (int x){return a[x];}
void Init(int R,int C){
r=R,c=C;
for(int i=1;i<=r;i++)
a[i].reset();
return ;
}
friend Matrix operator * (Matrix A,Matrix B){
Matrix C;
C.Init(A.r,B.c);
for(int i=1;i<=A.r;i++)
for(int k=1;k<=A.c;k++)
if(A[i][k])
C[i]|=B[k];
return C;
}
}f[Log+5][2],a,b;//f[k][0|1][u][v]:2^k 步 u 能否到 v
int main(){
n=read(),m=read();
f[0][0].Init(n,n),f[0][1].Init(n,n);
for(int i=1;i<=m;i++){
int u=read(),v=read(),p=read();
f[0][p][u][v]=1;
}
for(int k=1;k<=Log;k++){
f[k][0]=f[k-1][0]*f[k-1][1];
f[k][1]=f[k-1][1]*f[k-1][0];
}
int opt=0;
LL ans=0;
a.Init(1,n),a[1][1]=1;
for(int k=Log;k>=0;k--){
b=a*f[k][opt];
if(b[1].count()){
a=b,opt^=1;
ans+=(1ll<<k);
}
if(ans>(LL)1e18){
puts("-1");
return 0;
}
}
printf("%lld\n",ans);
return 0;
}
思考
學習到重定義 的方法,高興
以後記住鄰接矩陣轉移 優化