高斯消元学模板

模板大法还是kuangbin的好啊!!

上我Final Bin的链接:点我学高斯消元模板


习题在对应的地方有,在这附录自己的学习记录:

POJ1830

学习的第一个高斯消元的模板题:关键是怎么构造矩阵,解释有如下两篇博客很细致:

http://www.cnblogs.com/fstang/archive/2013/01/24/2874231.html

http://blog.sina.com.cn/s/blog_62ebd4410100h2qf.html

看完了之后,相信自己也能把模板套出来,代码都一样的,就不贴了


HDOJ4818

首先熟悉解释下题意:题目中会定义一个传递矩阵,把自己的分数给“相邻”的其他人,然后问是不是“稳定”的。需要求一个位置上的人,能够让第n-1个位置上的人得到“稳定”后的最大价值


分析见:http://www.cnblogs.com/kuangbin/p/3568145.html


代码从我bin处学习的,里面添加了自己的注释和对题的理解:


/*
	Main Focus:
	
	Your friend A’s ID is always (n-1).
	
	If there are multiple qualifying persons, 
	your friend A wants to know which one 
	can increase his RP to the maximum extent.
	
	Each of these lines will contain two integers 
	u and v (0 ≤ u, v < n), indicating u->v.
*/
double a[maxn][maxn],x[maxn];
int equ,var;

int Gauss(){
	int i,j,k,col,max_r;
	for(k=0,col=0;k<equ&&col<var;k++,col++){
		max_r=k;
		for(i=k+1;i<equ;i++)
			if (fabs(a[i][col])>fabs(a[max_r][col]))
				max_r=i;
		if (fabs(a[max_r][col])<eps) return 0;
		if (k!=max_r){
			for(j=col;j<var;j++)
				swap(a[k][j],a[max_r][j]);
			swap(x[k],x[max_r]);
		}
		x[k]/=a[k][col];
		for(j=col+1;j<var;j++) a[k][j]/=a[k][col];
		a[k][col]=1;
		for(i=0;i<equ;i++)
			if (i!=k){
				x[i]-=x[k]*a[i][k];
				for(j=col+1;j<var;j++)
					a[i][j]-=a[k][j]*a[i][col];
					a[i][col]=0;
			}
	}
	return 1;
}

vector<int> vec[maxn];
int g[maxn][maxn],du[maxn],add[maxn];

int main(){
	//input;
	int T,n,m;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		for(int i=0;i<=n;i++) vec[i].clear();
		memset(g,0,sizeof(g));
		memset(du,0,sizeof(du));
		int u,v;
		while(m--){
			scanf("%d%d",&u,&v);
			if (u==v) continue;
			g[u][v]=1;
		}
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				if (j!=i&&g[i][j]){
					du[i]++;
					vec[j].push_back(i);
				}
		equ=var=n;
		//equ表示方程个数
		//var表示变量个数
		for(int i=0;i<n;i++) x[i]=0;
		memset(a,0,sizeof(a));
		for(int i=0;i<n;i++){
			a[i][i]=-1;//自己的人品是全部贡献出去的 
			int sz=vec[i].size();
			for(int j=0;j<sz;j++){
				int v=vec[i][j];
				if (i==v) continue;
				a[i][v]=1.0/du[v];
				//i赚的是从与i相连的所有点贡献的(均分)
			}
		}
		for(int i=0;i<n;i++) a[n-1][i]=1;
		x[n-1]=1;
		//这个就是题目中询问的是否能够恒成立
		
		for(int k=0;k<n-1;k++)
			if (g[n-1][k]==0){
				for(int i=0;i<n-1;i++)
					if (g[n-1][i])
						a[i][var]=1.0/(du[n-1]+1);//有边就分账 
					else
						a[i][var]=0;//没边就清零 
				a[k][var]=1.0/(du[n-1]+1); 
				a[n-1][var]=1;
				add[var]=k;//标记,这是从第k个人来的 
				var++;
			}
		if (!Gauss()){
			printf("INF\n");
			continue;
		}
		double tt=x[n-1];
		double now=x[n-1];
		int ans=-1;
		for(int i=n;i<var;i++)
			if (x[n-1]/a[n-1][i]>now){//满足更新
				ans=add[i];
				now=x[n-1]/a[n-1][i];
			}
		printf("%d %d\n",1,ans);
	}
	return 0;
}


HDOJ3976

题解见:http://www.cnblogs.com/kuangbin/p/3428573.html

关键:a【u】【v】表示的是电流值

然后代码就能弄懂了

你可能感兴趣的:(ACM)