中石油训练赛 - Molecules(高斯消元解方程)

中石油训练赛 - Molecules(高斯消元解方程)_第1张图片

题目链接:点击查看

题目大意:笛卡尔坐标系上给出 n 个点,如果点为 ( -1 , -1 ) 说明该点的位置是不确定的,现在给出 m 个相连接的关系, 规定位置不确定的点会被周围相邻的点拉到平均位置上,题目需要确定出最终每个点的位置

题目分析:首先不难看出,x 和 y 是相互独立的,所以我们可以单独处理,因为 n 最大只有 100 ,所以我们可以对于每个位置列出一个线性方程,最后高斯消元直接求解即可

中石油训练赛 - Molecules(高斯消元解方程)_第2张图片

大概就是这样的转换,套入模板即可

代码:
 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
 
typedef long long LL;
 
typedef unsigned long long ull;
 
const int inf=0x3f3f3f3f;

const int N=110;

double a[N][N],x[N],y[N];

int n,m;

vectornode[N];

bool Gauss()
{
	for(int i=1;i<=n;++i)//枚举列(项) 
	{
		int max=i;
		for(int j=i+1;j<=n;++j)//选出该列最大系数 
		{
			if(fabs(a[j][i])>fabs(a[max][i]))
            //fabs是取浮点数的绝对值的函数
			{
				max=j;
			}
		}
		for(int j=1;j<=n+1;++j)//交换
		{
			swap(a[i][j],a[max][j]);
		}
		if(!a[i][i])//最大值等于0则说明该列都为0,肯定无解 
			return false;
		for(int j=1;j<=n;++j)//每一项都减去一个数(就是小学加减消元)
		{
			if(j!=i)
			{
				double temp=a[j][i]/a[i][i];
				for(int k=i+1;k<=n+1;++k)
				{
					a[j][k]-=a[i][k]*temp;
                    //a[j][k]-=a[j][i]*a[i][k]/a[i][i];
				}
			}
		}
	}
    //上述操作结束后,矩阵会变成这样
    /*
    k1*a=e1
    k2*b=e2
    k3*c=e3
    k4*d=e4
    */
    //所以输出的结果要记得除以该项系数,消去常数
	for(int i=1;i<=n;++i)
		a[i][n+1]/=a[i][i];
	return true;
}

void solve(double x[])
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n+1;j++)
			a[i][j]=0;
	for(int i=1;i<=n;i++)
	{
		if(x[i]!=-1)
		{
			a[i][i]=1;
			a[i][n+1]=x[i];
		}
		else
		{
			a[i][i]=node[i].size();
			for(auto v:node[i])
				a[i][v]=-1;
		}
	}
	Gauss();
	for(int i=1;i<=n;i++)
		x[i]=a[i][n+1];
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%lf%lf",x+i,y+i);
	for(int i=1;i<=m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		node[u].push_back(v);
		node[v].push_back(u);
	}
	solve(x);
	solve(y);
	for(int i=1;i<=n;i++)
		printf("%.5f %.5f\n",x[i],y[i]);









	return 0;
}

 

你可能感兴趣的:(数学)