矩阵操作来处理图

总结:

此类题目有一个明显的特点,是n个点或者n*n的矩阵,否则无法做矩阵运算

点数不能太大,因为矩阵操作的复杂度是O(N^3)的,所以大概最多只能有100个点

结果和移动次数有关,且一次只能移动一个点(经过一条边)

Codeforces Round #236 (Div. 2)——Strictly Positive Matrix

题意:

给一个n*n的矩阵a,保证a[i][i]>0,所有元素非负

若干次幂之后,问时候能保证矩阵中不含有零

分析:

首先说明一点,矩阵的数值是没有多少关系的,只有零和大于零的数有区别,不妨把大于零的数变成1。对于a*a,可以考虑到,如果求出来a[i][j]大于零,那么相当于i通过一个点可以到达j,那么a^k就可以理解为经过k个点,所有点能不能互相到达。矩阵保证了对角线均大于零,也就是说点i可以通过点i到达i,所以最后的结果就是求一下所有点是不是能互相到达即可(i如果能经过k个点到达j,那么经过大于k个点也能到达j)

所以,问题转化成求整个图的连通性

第一种方法,参照大神的代码,使用bitset来实现floyd算法

const int MAXN = 2100;

bitset<MAXN> ipt[MAXN];

int main()
{
//    freopen("in.txt", "r", stdin);
	int n;
	while (~RI(n))
	{
		REP(i, n) REP(j, n)
		{
			int t;
			RI(t);
			ipt[i][j] = !!t;
		}
		bool ok = true;
		REP(k, n) REP(i, n)
			if (ipt[i][k])
				ipt[i] |= ipt[k];
		REP(i, n) REP(j, n) if (ipt[i][j] == 0) ok = false;
		if (ok) puts("YES");
		else puts("NO");
	}
	return 0;
}

第二种方法,参照大神,如果点1能到达所有点,切所有点都能到达点1,那么整个图连通

const int MAXN = 2100;

vector<int> G[MAXN], RG[MAXN];
bool vis[MAXN], rvis[MAXN];
void dfs(int u)
{
	vis[u] = true;
	REP(i, G[u].size())
	{
		int v = G[u][i];
		if (!vis[v])
			dfs(v);
	}
}

void rdfs(int u)
{
	rvis[u] = true;
	REP(i, RG[u].size())
	{
		int v = RG[u][i];
		if (!rvis[v])
			rdfs(v);
	}
}
int main()
{
//    freopen("in.txt", "r", stdin);
	int n;
	while (~RI(n))
	{
		CLR(vis, false); CLR(rvis, false);
		REP(i, n)
		{
			G[i].clear();
			RG[i].clear();
		}
		REP(i, n) REP(j, n)
		{
			int t;
			RI(t);
			if (t)
			{
				G[i].push_back(j);
				RG[j].push_back(i);
			}
		}
		dfs(0); rdfs(0);
		bool ok = true;
		REP(i, n) if (!vis[i]) ok = false;
		REP(i, n) if (!rvis[i]) ok = false;
		if (ok) puts("YES");
		else puts("NO");
	}
	return 0;
}

福州大学第十一届程序设计竞赛——Nostop

题意:

给一个有向图,从点1出发,每次走一条边,K次之后必须在点N。每条边有一个花费,求最后的最小花费,不能到达输出-1

分析:

特点:点数比较少(可以保留所有的结果即cost矩阵),操作步骤比较多,每次的操作一致(均是走一步)

状态->操作->状态->操作->状态。。。

这个题和上个题的区别在于,这个题目给定了k,所以不能直接判断可达(而且没有保证点的自环)。

注意一点,long long的INF需要单独修改

const LL INF = 1e18;
const int MAXN = 60;

struct Matric
{
	LL a[MAXN][MAXN];
	int n;
} ipt;
Matric operator* (Matric x, Matric y)
{
	Matric ret; ret.n = x.n;
	REP(i, x.n) REP(j, x.n) ret.a[i][j] = INF;
    REP(i, x.n) REP(j, x.n) REP(k, x.n)
        ret.a[i][j] = min(ret.a[i][j], x.a[i][k] + y.a[k][j]);
    return ret;
}
Matric pow(Matric a, int b)
{
	Matric ret; ret.n = a.n;
	bool flag = false;
	while (b)
	{
		if (b & 1)
		{
			if (flag) ret = ret * a;
			else ret = a;
			flag = true;
		}
		a = a * a;
		b >>= 1;
	}
	return ret;
}
int main()
{
//    freopen("in.txt", "r", stdin);
	int T, v, e, k, a, b, d;
	RI(T);
	REP(kase, T)
	{
		RIII(v, e, k);
		ipt.n = v;
		REP(i, v) REP(j, v) ipt.a[i][j] = INF;
		REP(i, e)
		{
			RIII(a, b, d);
			a--; b--;
			ipt.a[a][b] = min(ipt.a[a][b], (LL)d);
		}
		ipt = pow(ipt, k);
		if (ipt.a[0][v - 1] != INF)
			cout << ipt.a[0][v - 1] << endl;
		else
			puts("-1");
	}
	return 0;
}

还有一个可以解决的是:求出从起点到每个点的路径数量

时间: 2024-07-31 02:47:49

矩阵操作来处理图的相关文章

Linear regression with one variable算法实例讲解(绘制图像,cost_Function ,Gradient Desent, 拟合曲线, 轮廓图绘制)_矩阵操作

%测试数据 'ex1data1.txt', 第一列为 population of City in 10,000s, 第二列为 Profit in $10,000s 1 6.1101,17.592 2 5.5277,9.1302 3 8.5186,13.662 4 7.0032,11.854 5 5.8598,6.8233 6 8.3829,11.886 7 7.4764,4.3483 8 8.5781,12 9 6.4862,6.5987 10 5.0546,3.8166 11 5.7107,3

Quartz2d 画饼状图 图形上下文栈 矩阵操作 裁剪圆角图片

画饼状图 - (void)drawRect:(CGRect)rect { // Drawing code // 需求:根据sections的数据,绘制多个扇形 // 1.获取上下文(Layer Graphics Context) CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.根据sections的个数,计算扇形的起始和结束位置来画扇形 NSInteger count = self.sections.count; // 如果没有数据,

poj3735—Training little cats(特殊操作转化为矩阵操作)

题目链接:http://poj.org/problem?id=3735 题目意思: 调教猫咪:有n只饥渴的猫咪,现有一组羞耻连续操作,由k个操作组成,全部选自: 1. g i 给第i只猫咪一颗花生 2. e i 让第i只猫咪吃光它的花生 3. s i j 交换猫咪i与猫咪j的花生 现将上述一组连续操作做m次后,求每只猫咪有多少颗花生? 思路:这道题难点在如何把这种奇怪的操作转化为矩阵操作,网络上看到一个画的很好的图,这里直接偷过来. 现在,对于每一个操作我们都可以得到一个转置矩阵,把k个操作的矩

MATLAB命令大全和矩阵操作大全

转载自: http://blog.csdn.net/dengjianqiang2011/article/details/8753807 MATLAB矩阵操作大全 一.矩阵的表示在MATLAB中创建矩阵有以下规则: a.矩阵元素必须在"[ ]"内: b.矩阵的同行元素之间用空格(或",")隔开: c.矩阵的行与行之间用";"(或回车符)隔开: d.矩阵的元素可以是数值.变量.表达式或函数: e.矩阵的尺寸不必预先定义. 二,矩阵的创建: 1.直接输

猫猫学IOS(三十二)UI之Quartz2D矩阵操作和图片剪切

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 矩阵操作 矩阵操作:(旋转,缩放,平移) 通过矩阵操作,把画出来的东西进行形变 旋转操作 方法:CGContextRotateCTM(<#CGContextRef c#>, <#CGFloat angle#>)该接受两个参数(图形上下文,弧度) 注意点:设置矩阵操作必须要在添加图形之前,如果设置在添加图形之后的话

OpenCV &mdash;&mdash; 矩阵操作

多通道的矩阵 -- 通道是连续的!! 要将指向该数据类型的指针移动到下一通道,我们只需要将其增加1.如果想访问下一个"像素"或者元素集,则需要一定的偏移量 矩阵的step元素是矩阵中行的长度,单位为字节.   #include "cv.h" #include "highgui.h" #include <IOSTREAM.H> int main(int argc,char** argv) { float vals[]={0.85,-0.

iOS开发UI篇—Quartz2D使用(矩阵操作)

iOS开发UI篇-Quartz2D使用(矩阵操作) 一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: 1 - (void)drawRect:(CGRect)rect 2 { 3 //画四边形 4 //获取图形上下文 5 CGContextRef ctx=UIGraphicsGetCurrentContext(); 6 //绘图 7 CGContextAddRect(ctx, CGRectMake(20, 50, 100, 100)); 8 //渲染

Opencv矩阵操作

分配矩阵空间: CvMat* cvCreateMat(int rows, int cols, int type); 释放矩阵空间: cvReleaseMat(&M); 数据类型宏定义: CV_<bit_depth>(S|U|F)C<number_of_channels> 复制矩阵: CvMat* M2;    M2=cvCloneMat(M1); 初始化矩阵: double a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; 要

matlab矩阵操作

1:求行数  nrow=size(matrix,1); 2:求列数  ncol=size(matrix,2); 3:矩阵合并 c1=[m1,m2]横向合并  c2=[m1;m2]纵向合并 m1= [5     2     3] ; m2=[1     2     3]; c1 =[5     2     3     1     2     3]; c2 =[ 5 2 3 1 2 3 ] matlab的下标从1开始,取matlab的元素直接用m[index]即可 取子矩阵 m[r1:rn,:]