已知有几个消防站了 问在哪再建一个消防站使得其他城市离最近的消防站距离总和最近
这个题哈,做了一星期才把zoj的测试数据给过了。。。悲剧啊悲剧。。。
最初留这题的时候,开始大家题都米看懂,导致做一天多了,按错的方向来了。。崩溃。浙大的要求是1秒,北大5秒内。
理解题意后改改,用dij+邻接矩阵,自己机子跑了8秒多。。。交到北大上,3秒多,过了。后来CW说用邻接表写,我那个纠结啊。。。我不喜欢链表啊不喜欢!!!觉得挺麻烦的,没办法,硬着头皮上吧!居然还写过了!提高到了2秒多,浙大站上依然TLE。
再然后,他们几个都用SPFA在浙大上写过了,弄得我也想去看SPFA,然后捏。。CW说用优先队列写,恩。。好吧,我又找了找优先队列的知识,C++里的,大数据运行不出来,小数据差不多都过了,真纠结。磨得都快没信心了都。。。后来CW说自己写的效率高,用堆。。就看堆排。。。理解了,但还是出不来。。。后来CW说给大家讲堆,关于堆的插入与删除,呃。。这个样子呀。。自己看着算法导论写了写插入与删除,理解了,挺好~~真正运用到1857的时候,依旧噩梦!不知道如何保存原来的下标,因为入堆后,排序了,下标就变了,然后就用结构体什么什么的。。。后来CW给提示哈,还得标记是否在堆里,在堆里的话如果更新的话还得找到相应的那个结构体然后更新。。。悲剧,要存下标的,想了想,发现我还是不笨滴。。。用有点小纠结的方法存了下标。。。然后的错误就是忘记把已经存在的消防站存进堆里了,如果没存的话,中间再存的话,有些点已经出堆更新不到了。。。
就这样纠结呀纠结,在一星期后的今天,我终于AC啦!!!哈哈哈哈哈哈哈哈哈!!!!
dij+邻接矩阵(zoj TLE poj AC)
#include <stdio.h> #include <stdlib.h> #include <memory.h> #include <limits.h> #include <time.h> #define N 700 int main(void) { int fnum,n,i,j,now,min,max,fresum,sum,tempnum,k; int map[N][N],hash[N],fire,x,y,length,flag[N],tempdis[N]; int dis[N],tempj,tempp,tempcha,mark; char str[50]; //freopen("b.in","r",stdin); //freopen("out.txt","w",stdout); while( scanf("%d %d",&fnum,&n)!= EOF ) { memset(flag,0,sizeof(flag)); for(i=1; i<=n; i++) { dis[i] = INT_MAX; for(j=1; j<=n; j++) map[i][j] = INT_MAX; map[i][i] = 0; } for(i=1; i<=fnum; i++) { scanf("%d",&fire); flag[fire] = 1; dis[fire] = 0; } getchar(); while( gets(str) && strlen(str) ) { sscanf(str,"%d%d%d",&x,&y,&length); map[x][y] = length; map[y][x] = length; } hash[fire] = 1; now = fire; sum = 0;mark = 0; for(j=1; j<=n; j++) { if(flag[j] == 0) mark = 1; } if( mark == 0 ) { printf("1/n"); continue; } for(j=1; j<=n; j++) //Dijkstra { for(i=1; i<=n; i++) { if( dis[i] > dis[now] + map[now][i] && map[now][i]!=INT_MAX ) dis[i] = dis[now] + map[now][i]; } min = INT_MAX; for(i=1; i<=n; i++) if( dis[i]<min && !hash[i]) { min = dis[i]; now = i; } hash[now] = 1; } max = 0; for(k=1; k<=n; k++) if( dis[k] > max ) { max = dis[k]; } fresum = INT_MAX; tempnum = 1; memcpy(tempdis,dis,(n+1)*sizeof(int)); tempp = 0; for(j=1; j<=n; j++) { int mmax = 0; if( flag[j] == 1 ) continue; memcpy(dis,tempdis,(n+1)*sizeof(int)); memset(hash,0,sizeof(hash)); now = j; dis[now] = 0; hash[now] = 1; for(k=1; k<=n; k++) { for(i=1; i<=n; i++) { if( dis[i] > dis[now] + map[now][i] && map[now][i]!=INT_MAX ) dis[i] = dis[now] + map[now][i]; } min = INT_MAX; for(i=1; i<=n; i++) if( dis[i] < min && !hash[i]) { min = dis[i]; now = i; } hash[now] = 1; } for(k=1; k<=n; k++) if( dis[k] > mmax ) { mmax = dis[k]; } tempcha = max - mmax; if( tempcha > tempp ) { tempp = tempcha; tempj = j; } } printf("%d/n",tempj); } return 0; }
dij+邻接表(zoj TLE poj AC)
#include <stdio.h> #include <stdlib.h> #include <memory.h> #include <limits.h> #define N 600 struct adjlist { int length; int num; struct adjlist *next; }; typedef struct adjlist adj; adj *p[N],node[N*N],*head[N]; int main(void) { int fnum,n,i,j,now,min,max,fresum,sum,tempnum,k,mmax; int hash[N],fire,x,y,length,flag[N]; int dis[N],count,to,tempdis[N],tempcha,tempk,tempp,tempj,mark; char str[50]; while( scanf("%d %d",&fnum,&n)!= EOF ) { memset( p,'/0',sizeof(p) ); memset( flag,0,sizeof(flag) ); memset( hash,0,sizeof(hash) ); memset( dis,0,sizeof(dis) ); mark = 0; for(i=1; i<=n; i++) { dis[i] = INT_MAX; } for(i=1; i<=fnum; i++) //输入已经有消防站的岔口 { scanf("%d",&fire); flag[fire] = 1; dis[fire] = 0; } getchar(); count = 1; while( gets(str) && strlen(str) ) { sscanf(str,"%d%d%d",&x,&y,&length); node[count].num = y; node[count].length = length; node[count].next = p[x]; p[x] = &node[count]; count++; node[count].num = x; node[count].length = length; node[count].next = p[y]; p[y] = &node[count]; count++; } for(i=1; i<=n; i++) head[i] = p[i]; for(j=1; j<=n; j++) { if(flag[j] == 0) mark = 1; } if( mark == 0 ) { printf("1/n"); continue; } hash[fire] = 1; now = fire; sum = 0; for(j=1; j<=n; j++) if( !flag[j] ) dis[j] = INT_MAX; for(i=1; i<=n; i++) { head[i] = p[i]; //指针指向头节点 } fresum = INT_MAX; tempnum = 1; memcpy(tempdis,dis,(n+1)*sizeof(int)); tempp = 0; max = INT_MAX; for(j=1; j<=n; j++) { int mmax = 0; if( flag[j] == 1 ) continue; memcpy(dis,tempdis,(n+1)*sizeof(int)); memset(hash,0,sizeof(hash)); now = j; dis[now] = 0; hash[now] = 1; for(i=1; i<=n; i++) head[i] = p[i]; for(i=1; i<=n; i++) //Dijkstra { while( head[now]!= NULL ) { to = head[now]->num; if( dis[to] > dis[now] + head[now]->length) dis[to] = dis[now] + head[now]->length; head[now] = head[now]->next; } min = INT_MAX; for(k=1; k<=n; k++) { if(dis[k] < min && !hash[k]) { now = k; min = dis[k]; } } hash[now] = 1; } for(k=1; k<=n; k++) printf("%d ",dis[k]); putchar('/n'); for(k=1; k<=n; k++) if( dis[k] > mmax ) { mmax = dis[k]; } if( max > mmax ) { max = mmax; tempj = j; } } printf("/n%d/n",tempj); } system("pause"); return 0; }
dij+邻接表+堆优化(zoj AC poj AC)
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <limits.h> #include <queue> #define N 600 using namespace std; struct adjlist { int length; int num; struct adjlist *next; }; struct dist { int num; int length; }; typedef struct adjlist adj; typedef struct dist d; adj *p[N],node[N*N],*head[N]; d tempdis[N],temp; int point[N]; int heap_size; void heappaixu(d a[],int i) { int l_child,r_child,larg; d temp; while(1) { l_child = i<<1; r_child = l_child+1; if( l_child <= heap_size && a[l_child].length < a[i].length ) larg = l_child; else larg = i; if(r_child <= heap_size && a[r_child].length < a[larg].length) { larg = r_child; } if( larg != i ) { point[a[i].num] = larg; point[a[larg].num] = i; temp = a[i]; a[i] = a[larg]; a[larg] = temp; i = larg; } else break; } } void Insertheap(d a[],d key) { int i,parent; d temp; heap_size++; a[heap_size] = key; i = heap_size; while( i>1 ) { parent = i>>1; if( a[i].length < a[parent].length ) { point[a[i].num] = parent; point[a[parent].num] = i; temp = a[i]; a[i] = a[parent]; a[parent] = temp; i = parent; } else break; } } void Delheap(d a[]) { point[a[heap_size].num] = 1; a[1] = a[heap_size]; heap_size--; heappaixu(a,1); } /*******************************************main********************************************/ int main(void) { int fnum,n,i,j,now,min,max,fresum,sum,k,mmax; int hash[N],fire,x,y,length,flag[N]; int count,to,tempj,mark,dis[N],t[N]; char str[50]; freopen("b.in","r",stdin); freopen("out.txt","w",stdout); while( scanf("%d %d",&fnum,&n)!= EOF ) { memset( p,'/0',sizeof(p) ); memset( flag,0,sizeof(flag) ); memset( dis,0,sizeof(dis)); mark = 0; for(i=1; i<=fnum; i++) //输入已经有消防站的岔口 { scanf("%d",&fire); flag[fire] = 1; dis[fire] = 0; } getchar(); count = 1; while( gets(str) && strlen(str) ) { sscanf(str,"%d%d%d",&x,&y,&length); node[count].num = y; node[count].length = length; node[count].next = p[x]; p[x] = &node[count]; count++; node[count].num = x; node[count].length = length; node[count].next = p[y]; p[y] = &node[count]; count++; } for(i=1; i<=n; i++) head[i] = p[i]; for(j=1; j<=n; j++) { if(flag[j] == 0) mark = 1; } if( mark == 0 ) { printf("1/n"); continue; } /**********************************************************************************/ max = INT_MAX; for(i=1; i<=n; i++) { head[i] = p[i]; //指针指向头节点 } for(i=1; i<=n; i++) if( !flag[i] ) dis[i] = INT_MAX; memcpy(t,dis,(n+1)*sizeof(int)); /*******************************************************************************/ for(j=1; j<=n; j++) { if( flag[j] == 1 ) continue; memcpy(dis,t,(n+1)*sizeof(int)); memset( point,0,sizeof(point) ); memset( hash,0,sizeof(hash) ); mmax = 0; heap_size = 0; now = j; dis[now] = 0;hash[now] = 1; for(i=1; i<=n; i++) head[i] = p[i]; for(k=1; k<=n; k++) head[k] = p[k]; for(k=1; k<=n; k++) if( flag[k] ) { dis[k] = 0; temp.length = 0; temp.num = k; Insertheap(tempdis,temp); point[k] = heap_size; hash[k] = 1; } /**************************************************************************/ for(i=1; i<=n; i++) //Dijkstra { while( head[now]!= NULL ) { to = head[now]->num; if( dis[to] > dis[now] + head[now]->length ) { dis[to] = dis[now] + head[now]->length; if( hash[to] == 1 ) { tempdis[point[to]].length = dis[to]; } else { temp.length = dis[to]; temp.num = to; Insertheap(tempdis,temp); point[to] = heap_size; hash[to] = 1; } } head[now] = head[now]->next; } now = tempdis[1].num; Delheap(tempdis); } /**************************************************************************/ for(k=1; k<=n; k++) if( dis[k] > mmax ) { mmax = dis[k]; } if( max > mmax ) { max = mmax; tempj = j; } } printf("%d/n",tempj); } system("pause"); return 0; }
最后一个是我写程序以来最长的代码!!!!!!哈哈哈哈哈哈哈哈哈~~~~~