poj 3613 Cow Relays

这是什么鬼??????

floyd+矩阵乘法?????

不是很懂你们奶牛,真会玩。

问题是求无向图上两点间经过k条边的最短路。

定义floyd矩阵乘法(我瞎扯的)为A[i][j]=min(B[i][k]+C[k][j])

然后发现这个满足结合律哎。

如果B为经过x条边的答案,C为经过y条边的答案,那么A为经过x+y条边的答案

好神奇

于是就可以直接套矩阵快速幂了。

真是6的不行

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100+5;
int n;
struct matrix{
	int a[N][N];
	matrix(){memset(a,0x3f,sizeof(a));}
	void init(){memset(a,0x3f,sizeof(a));}
	void clear(){memset(a,0,sizeof(a));}
	void print(){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++)
			printf("%d ",a[i][j]);
			putchar('\n');
		}
	}
	matrix operator * (const matrix &b)const{
		static matrix ans;
		ans.init();
		for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		ans.a[i][j]=min(ans.a[i][j],a[i][k]+b.a[k][j]);
		return ans;
	}
	matrix operator ^ (int k)const{
		static matrix ans,b;
		ans.init();
		for(int i=1;i<=n;i++)ans.a[i][i]=0;
		memcpy(b.a,a,sizeof(a));
		for(;k;k>>=1,b=b*b)if(k&1)ans=ans*b;
		return ans;
	}
}g;
int idx[1005];
int id(int x){
	if(!idx[x])idx[x]=++n;
	return idx[x];
}
int main(){
	//freopen("a.in","r",stdin);
	int s,t,m,k;
	scanf("%d%d%d%d",&k,&m,&s,&t);
	s=id(s);t=id(t);
	while(m--){
		int u,v,w;scanf("%d%d%d",&w,&u,&v);
		u=id(u);v=id(v);
		g.a[u][v]=min(g.a[u][v],w);
		g.a[v][u]=min(g.a[v][u],w);
	}
	g=g^k;
	printf("%d\n",g.a[s][t]);
	return 0;
}


你可能感兴趣的:(poj 3613 Cow Relays)