2014 ACM 并查集-p6
- 格式:pdf
- 大小:941.55 KB
- 文档页数:17


大数除法16进制#include <stdio.h>#include <string.h>#define max 200int i;char jinzhi[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; int chu(char a[],char b[]){int shan, yu;for(yu = i = 0; a[i]; i++){yu = yu * 10 + a[i] - '0';shan = yu / 16;yu = yu % 16;b[i] = shan + '0';}b[i] = 0;return yu;}int judge(char a[]){for(i = 0; a[i]; i++)if(a[i] != '0')return 0;return 1;}void f(char a[]){int newbig;if(!judge(a)){char b[max];newbig = chu(a,b);f(b);printf("%c",jinzhi[newbig]);}}int main(void){char bigint[max];while(scanf("%s", bigint) == 1){if(strlen(bigint) == 1 ){if(bigint[0] == '0')return 0;}f(bigint);printf("\n");memset(bigint,'0',sizeof(bigint));}return 0;}最大公约数int GCD(int num1,int num2)//最大公约数{if ( num1 % num2 == 0){return num2;}elsereturn GCD( num2,num1 % num2) ;}最小公倍数int LCM(int a,int b)//最小公倍数{int temp_lcm;temp_lcm=a*b/GCD(a,b); //最小公倍数等于两数之积除以最大公约数return temp_lcm;}//求至少多少天相遇,同时出发,至少多少长方形堆正方体,分元宝类问题都是运用最小公倍数最小生成树#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int inf = ( 1 << 20 ) ;int p[27]; // 并查集,用于判断两点是否直接或间接连通struct prog{int u;int v;int w;}map[80];//存储边的信息,包括起点/终点/权值bool cmp ( prog a , prog b){//排序函数,将边根据权值从小到大排return a.w<b.w;}int find(int x){//并查集的find,不解释return x==p[x]?x:p[x]=find(p[x]);}//减枝void join(int x,int y,int i){int fx=find(x),fy=find(y);if(fx!=fy){pre[fx]=fy;if(i!=-1) fee+=a[i].x;}return;}int main(){int n;while ( cin >> n , n ){int i , j ;for ( i = 0 ; i < 27 ; i ++ )p[i] = i ;//并查集初始化int k = 0 ;for ( i = 0 ; i < n - 1 ; i ++ ){//构造边的信息char str[3];int m;cin >> str >> m ;for ( j = 0 ; j < m ; j ++ ,k ++ ){char str2[3];int t;cin >> str2 >> t ;map[k].u=(str[0]-'A');map[k].v=(str2[0]-'A');map[k].w=t;}}sort ( map , map + k , cmp );//将边从小到大排序int ans=0; //所要求的答案for ( i = 0 ; i < k ; i ++ ){int x = find(map[i].u);int y = find(map[i].v);printf("%d%d\n",x,y);if( x!=y){//如果两点不在同一连通分量里,则将两点连接,并存储该边ans+=map[i].w;p[x]=y;}}cout<<ans<<endl;}return 0;}最大连续子序列-1235#include <stdio.h>#include <math.h>#include <string.h>#include <algorithm>int a[10010],maxsum,t,e,n;void ff(){int i,l,j,sum;for(i = 0; i < n; i++){sum = 0;for(l = i; l < n; l++){sum += a[l];if(sum > maxsum){maxsum = sum;t = i;e = l;// printf("%d\n",maxsum);}// printf("%d %d %d\n",i,l,sum);}}}int main(){//freopen("1235input.txt","r",stdin);int f,i;while(scanf("%d",&n)&&n){memset(a,0,sizeof(a));f =0;maxsum = -10000;for(i = 0; i < n; i++){scanf("%d",&a[i]);if(a[i] < 0)f++;}if(f == n){maxsum = 0;t = 0;e = n-1;}elseff();printf("%d %d %d\n",maxsum,a[t],a[e]);}return 0;}素数表int a[10000];//1为素数void ff(){memset(a,1,sizeof(a));for(i=2;i<=10000;i++){if(a[i]==1){printf("%d ",i);for(l=i;l<=10000;l++){if(a[l]==1)if(l%i==0)a[l]=0;}}}}================int a[10000];void ff(){memset(a,1,sizeof(a));for(int i = 2; i < 10000; i++){if(a[i] == 0){int l = i;while(i * l < 10000){a[i*l]=0;l++;} }}}BFSinclude <stdio.h>#include <string.h>int x, y, mx, my,step;char map[110][110];int move[8][2]={-1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1};int recode[110][110];int f[110][110];struct duili{int x;int y;}a[110*110];bool judge(int m, int n){if(map[m][n]== '.' &&f[m][n]==2&& m>0 &&n>0&&m<y+1&&n<x+1) return 1;elsereturn 0;}int bfs(int i,int j){int front = 0,rear = 1;step = -1;recode[i][j] = 0; f[i][j]=1;a[front].x = i;a[front].y = j;while(front < rear){int xx = a[front].x, yy = a[front].y;front++;for(i = 0; i < 8; i++ ){if(judge(xx + move[i][0],yy + move[i][1])){f[xx + move[i][0]][yy + move[i][1]] =1 ;recode[xx + move[i][0]][yy + move[i][1]] = recode[xx][yy] + 1;a[rear].x = xx + move[i][0];a[rear].y = yy + move[i][1];rear++;if (recode[xx + move[i][0]][yy + move[i][1]] > step)step = recode[xx + move[i][0]][yy + move[i][1]];}}// for(int i = y; i > 0; i--)// {// for(int j = 1; j <= x; j++)// printf("%d",f[i][j]);// printf("\n");// }// printf("\n");}return step;}int main(){scanf("%d%d%d%d",&x, &y, &mx, &my);memset(map,0,sizeof(map));memset(f,0,sizeof(f));memset(recode,0,sizeof(recode));getchar();for(int i = y; i > 0; i--){for(int j = 1; j <= x; j++){scanf("%c",&map[i][j]);if(map[i][j]=='.')f[i][j]=2;}getchar();}// for(int i = y; i > 0; i--)// {// for(int j = 1; j <= x; j++)// printf("%c",map[i][j]);// printf("\n");// }printf("%d\n",bfs(mx,my));return 0;}CD_ROOM#include <stdio.h>int maxn;int n;int arr[20];int tempmax;void ff(int cur, int sum){if (sum > maxn)return;if (cur == n){tempmax >?= sum;return;}ff(cur + 1, sum);sum += arr[cur];ff(cur + 1, sum);}int main(void){while (tempmax = 0, scanf("%d", &n) == 1) {scanf("%d", &maxn);for (int i = 0; i < n; i++)scanf("%d", arr + i);ff(0, 0);printf("%d\n", tempmax);}return 0; }Floyed(最短路径)(可以有圈)#include <iostream>#include <string>#include <map>using namespace std;const int MAXN = 31;typedef double ValueType;//数据类型void Floyed(ValueType g[][MAXN],int n)//佛洛依德算法{for(int k=0;k<n;++k)for(int i=0;i<n;++i)for(int j=0;j<n;++j)if(g[i][j]<g[i][k]*g[k][j]) g[i][j] = g[i][k]*g[k][j];//尽可能使汇率大,这里是乘法(*)}int main(){int n,m,i,Case=0;string name,sour,dest;V alueType value;map<string,int> Currency; //用map实现name和index之间的转换V alueType graph[MAXN][MAXN];while(cin>>n){if(n==0) break;Currency.clear();memset(graph,0,sizeof(graph));for(i=0;i<n;++i)//n个顶点{cin>>name;Currency[name] = i;graph[i][i] = 1;}cin>>m;//m条边for(i=0;i<m;++i)//输入边信息创建图{cin>>sour>>value>>dest;graph[Currency[sour]][Currency[dest]] = value;}Floyed(graph,n);//佛洛依德求各个节点之间的bool ok = false;for(int i=0;i<n;++i)//求自身到自身的汇率(回路) if(graph[i][i]>1){ok=true;break;}cout<<"Case "<<++Case<<": ";if(ok) cout<<"Yes\n";else cout<<"No\n";}return 0;}3个for#include<stdio.h>#define MAX 100000000int main(){int n,m,a,b,t,i,j,k,map[202][202];while(scanf("%d%d",&n,&m)!=EOF){for(i=1;i<=n;i++)for(j=1;j<=n;j++)map[i][j]=MAX;while(m--){scanf("%d%d%d",&a,&b,&t);map[a][b]=t;map[b][a]=t;}for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(map[i][k]+map[k][j]<map[i][j])map[i][j]=map[i][k]+map[k][j];scanf("%d%d",&a,&b);if(map[a][b]==MAX||b>n||a<1)printf("-1\n");elseprintf("%d\n",map[a][b]);}}Dijkstra算法+注释#include <iostream>#include <string.h>#include <limits.h>#include <stdio.h>//hdu1874using namespace std;int map[1002][1002];int main(){int n,m;while(~scanf("%d%d",&n,&m)){int visted[205],dis[205];memset(visted,0,sizeof(visted)); //访问数组初始化for(int i=1;i<=n;++i){dis[i]=INT_MAX; //初始化两点之间的最短路径!!for(int j=1;j<=n;++j)map[i][j]=INT_MAX; //初始化两点间距离!!map[i][i]=0;}int a,b,c;while(m--){scanf("%d%d%d",&a,&b,&c);//输入两点间最短距离if(c<map[a][b])map[a][b]=map[b][a]=c;}int begin ,end ,pos;scanf("%d%d",&begin,&end);pos=begin;visted[pos]=1;//访问初始起始点。
acm模板整理和使用方法[acm模板整理和使用方法]ACM模板指的是计算机科学中常用的算法模板,是计算机专业的学生在学习算法和数据结构时必需掌握的内容。
ACM模板整理和使用方法主要包括以下问题:一、为什么要使用ACM模板?ACM模板能使算法实现变得更简单、更方便、更快捷。
尤其在ACM竞赛中,使用优秀的模板可以节省编程时间,避免出现冗余代码,使得编程效率大幅提升。
二、哪些算法需要掌握?许多常见的算法,如快速排序、线段树、并查集、Kruskal算法、Dijkstra算法、最小生成树问题等,都需要掌握。
因此,算法学习和掌握是使用ACM模板的前提。
三、如何整理和使用ACM模板?1.整理ACM模板将常用的算法的代码整理,以函数或者类的形式存放在一个文件中。
注意代码要有良好的注释,易于阅读和理解。
2.旧的代码调试如果有其他ACM竞赛选手或者教练的旧代码,需要先将其调试通过。
因为在ACM比赛中,时间十分宝贵。
如果没有调试好的代码可以使用,建议可以使用OJ网站上的代码进行练习。
3.在比赛中使用和修改模板在ACM比赛中,选手需要快速编写正确的程序并提交到OJ网站。
使用模板可以节省时间和精力,但有时候需要针对具体的问题进行修改。
在修改时需要小心,一定要保证修改后的代码与原始模板的代码所实现的算法是等效的。
4.维护和更新模板ACM模板需要不断地维护和更新,特别是在涉及到新的算法或者数据结构时。
保证ACM模板的有效性和及时性非常重要,这需要持续的学习和探索。
四、如何学习和掌握ACM模板?1.选择学习和观察别人的代码一个好的方式是看国内和国际大佬们的代码,学习他们的代码风格和思考方式。
了解其他人的ACM模板如何实现,可以帮助你提高代码风格和技术水平。
2.探索自己不熟悉的算法和数据结构ACM竞赛中考察的算法不限于常见的算法,还包括各种数论、图论、动态规划等。
掌握这些算法和数据结构可以提高解题的速度和质量。
在掌握新算法之前,阅读相关论文或文章,掌握其基本原理和实现方法。
并查集小结有关并查集大体分为三类题:1.普通并查集;POJ-1611、POJ-2524、POJ-22362.种类并查集;POJ-1703、POJ-2492、POJ-1182、POJ-1733、POJ-1988、POJ-14173.扩展并查集(主要是必须指定合并时的父子关系,或者统计一些数据,比如此集合内的元素数目。
)POJ-1611 裸的水的并查集POJ-2524 裸的并查集POJ-2236 裸的并查集,小加一点计算几何POJ-1703 种类并查集(两个互斥集合)题目大意是:有两个帮派,告诉你那两个人属于不同的帮派,让你判断某两个人得是否在一个帮派中。
思路一:并查集。
一开始想多了,原因是自己还没有完全理解。
并查集的核心是用集合里的一个元素代表整个集合,集合里所有元素都指向这个元素,称它为根元素。
集合里任何一个元素都能到达根元素。
这一题里,设数组p[MAXSIZE][2],p[i][0]=j表示i的父亲是j,p[i][1]=j表示i与j不在同一个集合里面。
如果是D命令的话,把a放到p[b][1]的集合里,把b放到p[a][1]的集合里;如果是A命令的话,查询a,b的根元素:1. 根元素相同,a,b在同一个集合里;2. 根元素不同,但a与p[b][1]的根元素相同,a,b不在一个集合里;3.否则,a,b还没有确定。
思路二:并查集!如果两个人不在一个帮派中,那就连一条边,权值为1。
像银河英雄传说中的那样,这里我们用before[x]来记录x到根节点的距离。
对于一个询问,我们先判断他们是否在一个集合中。
如果不在,则他们的关系还未确定。
如果在一个集合中,并且他们到根的距离Mod2的值相等,则他们属于同一个帮派。
否则不是同一个帮派。
(为什么,其实很简单,只要你肯画画图就行了)。
那如何将两个集合合并呢??先来看下面一个性质。
对于这个图红边是读入的有矛盾的边,其中边上的权值为两点间的距离。
黄边是我们进行合并后要加入的边。