省选专练【POI2015】Wycieczki

20 篇文章 0 订阅
4 篇文章 0 订阅

什么K短路?

启发式搜索啊

TMMMP没有源汇

再一看:w小的可怜,k大的惊人 由数据规模分析算法必须得是log的 什么是log的? 数位上操作 倍增floyd感受下? 但是!这个题k太大了矩阵乘法还会炸精度 特判负数。。。

辣么拆点(真没搞网络流)

一个点拆三个点,表示可达性为1

然后利用T(0,0)的自环转移

#include<bits/stdc++.h>
using namespace std;
typedef int INT;
const int N=130;
#define int long long
#define Exit {res.a[0][0]=-1;return res;}
inline void read(int &x){
	x=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int n,m,K;
int idx[N][3]={};
int tot=0;
struct Matrix{
	int a[N][N];
	Matrix(){
		memset(a,0,sizeof(a));
	}
	friend Matrix operator *(Matrix A,Matrix B){
		Matrix C;
		for(int i=0;i<=tot;i++){
			for(int j=0;j<=tot;j++){
				for(int k=0;k<=tot;k++){
					C.a[i][k]+=(A.a[i][j]*B.a[j][k]);
				}
			}
		}
		return C;
	}
}a[68],b,c;
int cnt[N]={};
/*struct Matrix{
    int a[N][N];
    Matrix(){
        memset(a,0,sizeof(a));
    }
    Matrix operator *(const Matrix &A)const{
        Matrix res;
//        for(int i=0;i<=tot;i++)
//            for(int j=0;j<=tot;j++)
//                if(a[i][j]<0||A.a[i][j]<0)Exit;
        for(int i=0;i<=tot;i++)
            for(int j=0;j<=tot;j++)
                if(a[i][j]){
                    for(int k=0;k<=tot;k++)
                        if(A.a[j][k]){
//                            if(a[i][j]>K/A.a[j][k])Exit;
                            res.a[i][k]+=a[i][j]*A.a[j][k];
//                            if(res.a[i][j]>K)Exit;
                        }
                }
        return res;
    }
}a[65],b,c;*/
bool check(){
	if(b.a[0][0]<0)return false;
	int sum=0;
	for(int i=1;i<=tot;i++){
		if(b.a[0][i]&&cnt[i]){
			if(b.a[0][i]<0)return false;
			if(b.a[0][i]>K/cnt[i])return false;
			sum+=b.a[0][i]*cnt[i];
			if(sum>=K)return false; 
		} 
	}
	return sum<K;
}
INT main(){
	read(n);
	read(m);
	read(K); 
	for(int i=1;i<=n;i++){
		for(int j=0;j<3;j++){
			idx[i][j]=++tot;	
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<2;j++){
			a[0].a[idx[i][j]][idx[i][j+1]]++;
		}
		a[0].a[0][idx[i][0]]++;
	}
	a[0].a[0][0]++;//自环 
	for(int i=1;i<=m;i++){
		int u,v,w;
		read(u);
		read(v);
		read(w);
		cnt[idx[u][w-1]]++;
		a[0].a[idx[u][w-1]][idx[v][0]]++;
	}
	int Max=K*3;
	int ans=0;
	int len=0;
	while(((int)1<<len)<=Max)len++;
//	len--;
	for(int i=1;i<len;i++){
		a[i]=a[i-1]*a[i-1];
	}
	c.a[0][0]=1;
	for(int i=len-1;i>=0;i--){
		b=c*a[i];
		if(check()){
//			cout<<i<<" ";
			ans|=((int)1<<i);
			memcpy(c.a[0],b.a[0],sizeof(b.a[0]));
		}
	}
	ans++;
	//cout<<ans<<" ";
	if(ans>=Max)ans=-1;
	cout<<ans;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值