畅通工程,继续畅通工程,畅通工程再续,多种解法
2015-08-11 15:05
387 查看
继续畅通工程
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17822 Accepted Submission(s): 7672
[align=left]Problem Description[/align]
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。
[align=left]Input[/align]
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。
当N为0时输入结束。
[align=left]Output[/align]
每个测试用例的输出占一行,输出全省畅通需要的最低成本。
[align=left]Sample Input[/align]
3 1 2 1 0 1 3 2 0 2 3 4 0 3 1 2 1 0 1 3 2 0 2 3 4 1 3 1 2 1 0 1 3 2 1 2 3 4 1 0
[align=left]Sample Output[/align]
3 1 0
题解:
方法一:克鲁斯卡尔算法;
代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> const int MAXN=110; int sum; struct Node { int s,e,d,ol; }; Node dt[MAXN*MAXN/2]; int pre[MAXN]; void initial(){ memset(pre,0,sizeof(pre)); memset(dt,0,sizeof(dt)); } int find(int x){ return pre[x]= x==pre[x]?x:find(pre[x]); } int cmp(const void *a,const void *b){ if( (*(Node *)a).ol != (*(Node *)b).ol)return (*(Node *)b).ol-(*(Node *)a).ol; else return (*(Node *)a).d-(*(Node *)b).d; } void merge(Node a){ int f1,f2; if(!pre[a.s])pre[a.s]=a.s; if(!pre[a.e])pre[a.e]=a.e; f1=find(a.s); f2=find(a.e); if(f1!=f2){ pre[f1]=f2; if(!a.ol)sum+=a.d; } } int main(){ int N,t; while(~scanf("%d",&N),N){ initial();sum=0; t= N*(N-1)/2; int i,j; for(i=0;i<t;i++) scanf("%d%d%d%d",&dt[i].s,&dt[i].e,&dt[i].d,&dt[i].ol); qsort(dt,t,sizeof(dt[0]),cmp); for(int i=0;i<t;i++){ merge(dt[i]); } printf("%d\n",sum); } return 0; }
方法二:prime:
代码:
#include<stdio.h> #include<string.h> const int INF=0x3f3f3f3f; const int MAXN=110; int vis[MAXN],map[MAXN][MAXN],low[MAXN]; int N; void prime(){ memset(vis,0,sizeof(vis)); for(int i=1;i<=N;i++)low[i]=map[1][i]; vis[1]=1; int k,temp,min=0; for(int i=1;i<=N;i++){ temp=INF; for(int j=1;j<=N;j++) if(!vis[j]&&temp>low[j])temp=low[k=j]; if(temp==INF){ printf("%d\n",min); break; } min+=temp; vis[k]=1; for(int j=1;j<=N;j++){ if(!vis[j]&&low[j]>map[k][j])low[j]=map[k][j]; } } } int main(){int a,b,c,d,M; while(~scanf("%d",&N),N){ M=N*(N-1)/2; memset(map,INF,sizeof(map)); //printf("%d %d\n",M,N); // for(int i=0;i<10;i++)for(int j=0;j<10;j++)printf("%d ",map[i][j]); while(M--){ scanf("%d%d%d%d",&a,&b,&c,&d); if(d)map[a]=map[b][a]=0; else if(c<map[a][b])map[a][b]=map[b][a]=c; } prime(); } return 0; }
[align=center][b]欢迎参加——每周六晚的BestCoder(有米!) [/align] |
畅通工程Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 21373 Accepted Submission(s): 9196 [align=left]Problem Description[/align] 省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。 [align=left]Input[/align] 测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N 行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。 [align=left]Output[/align] 对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。 [align=left]Sample Input[/align] 3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100 [align=left]Sample Output[/align] 3 ? |
方法一:克鲁斯卡尔算法;
代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> struct Node { int s,e,dis; }; Node road[110]; int pre[110]; int N,M; int cmp(const void *a,const void *b){ return *(int *)a-*(int *)b; } int find(int x){ return x==pre[x]?x:find(pre[x]); } bool merge(int x,int y){ int f1,f2; f1=find(x);f2=find(y); if(f1!=f2){ pre[f1]=f2;return true; } return false; } void initial(){memset(pre,0,sizeof(pre));} int main(){ while(~scanf("%d%d",&N,&M),N){ for(int i=0;i<N;i++)scanf("%d%d%d",&road[i].s,&road[i].e,&road[i].dis); qsort(road,N,sizeof(road[0]),cmp); int num=0; initial(); for(int i=0;i<N;i++){ if(!pre[road[i].s])pre[road[i].s]=road[i].s; if(!pre[road[i].e])pre[road[i].e]=road[i].e; if(merge(road[i].s,road[i].e))num+=road[i].dis; }int flot=0; for(int i=1;i<=M;i++){ if(!pre[i]||i==pre[i])flot++; if(flot>1)break; } if(flot>1)puts("?"); else printf("%d\n",num); } return 0;}
方法二:prime算法:
#include<stdio.h> #include<string.h> const int INF=0x3f3f3f3f; const int MAXN=110; int map[MAXN][MAXN],vis[MAXN],low[MAXN]; int N,M,min; void prime(){ memset(vis,0,sizeof(vis));//记得初始化 int flot=1,k; for(int i=1;i<=M;i++) low[i]=map[1][i];//初始化low数组,刚开始已选集合{1}与此集合相连的权值为集合low vis[1]=1;//1在集合中visit【1】=1; for(int i=1;i<=M;i++){ int temp=INF;//记得初始化; for(int j=1;j<=M;j++){//找最小权值; if(!vis[j]&&temp>low[j]){ temp=low[k=j]; } } if(temp==INF){//找不到就判断; if(flot!=M)puts("?"); else printf("%d\n",min); break; } min+=temp; flot++;//代表当前已选集合中的元素个数; vis[k]=1; for(int i=1;i<=M;i++){//更新low数组;使其与已选数组相连的权值小; if(!vis[i]&&low[i]>map[k][i]) low[i]=map[k][i]; } } } int main(){ int a,b,d; while(~scanf("%d%d",&N,&M),N){ min=0;//刚开始min忘初始化了。。。 memset(map,INF,sizeof(map));//INF初始化为0xfffffff就不行,都是-1了 //for(int i=0;i<10;i++)for(int j=0;j<10;j++)printf("%d ",map[i][j]); for(int i=0;i<N;i++){ scanf("%d%d%d",&a,&b,&d); if(d<map[a])//此处不能少。。。 map[a][b]=map[b][a]=d; } prime(); } return 0; }
畅通工程再续
[b]Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)Total Submission(s) : 46 Accepted Submission(s) : 20
[align=left]Problem Description[/align]
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
[align=left]Input[/align]
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
[align=left]Output[/align]
每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
[align=left]Sample Input[/align]
2 2 10 10 20 20 3 1 1 2 2 1000 1000
[align=left]Sample Output[/align]
1414.2 oh!
题解:qsort写错了,wa了无数次;也可以设个变量num=1;每加进一个点或者一个树时就num++最后与n比较,相等则连通;
代码一:克鲁斯卡尔
#include<stdio.h> #include<stdlib.h> #include<math.h> #include<string.h> double distant(int ax,int ay,int bx,int by){ int x=bx-ax,y=by-ay; double s; s=x*x+y*y; s=sqrt(s); return s; } int pre[110]; struct Node{ int s,e; double d; }; Node die[10010]; int find(int x){ return pre[x]= x==pre[x]?x:find(pre[x]); } double minmoney; int cmp(const void *a,const void *b){ if((*(Node *)a).d<(*(Node *)b).d)return -1; else return 1; } void merge(Node a){ if(pre[a.s]==-1)pre[a.s]=a.s; if(pre[a.e]==-1)pre[a.e]=a.e; int f1=find(a.s),f2=find(a.e); if(f1!=f2){ pre[f1]=f2; minmoney+=a.d; } } void initial(){ memset(pre,-1,sizeof(pre)); memset(die,0,sizeof(die)); } int nx[110],ny[110]; int main(){ int T,C; scanf("%d",&T); while(T--){minmoney=0; initial(); // for(int i=0;i<110;i++)printf("%d",pre[i]); scanf("%d",&C); for(int i=0;i<C;i++){ scanf("%d%d",&nx[i],&ny[i]); } int k=0; for(int i=0;i<C;i++){ for(int j=i+1;j<C;j++){ double dis=distant(nx[i],ny[i],nx[j],ny[j]); //printf("%lf ",dis); if(dis>=10&&dis<=1000){ die[k].s=i;die[k].e=j; die[k].d=dis; k++; } } } //printf("%d\n",k); qsort(die,k,sizeof(die[0]),cmp); for(int i=0;i<k;i++){ merge(die[i]); } int flot=0; for(int i=0;i<C;i++){ if(pre[i]==i||pre[i]==-1)flot++; //if(flot>1)break; } //printf("%d\n",flot); if(flot>1) puts("oh!"); else printf("%.1lf\n",minmoney*100); } return 0; }
代码二:
无语,又错了好久,然后发现初始化map出错,对于double数组不能像int那样初始化;
代码:
#include<stdio.h> #include<string.h> #include<math.h> const int INF=0x3f3f3f3f; const int MAXN=110; int N,vis[MAXN]; double map[MAXN][MAXN],low[MAXN]; double fd(int ax,int ay,int bx,int by){ int x=bx-ax; int y=by-ay; int s=x*x+y*y; return sqrt(s); } void prime(){ int flot=1,k; double min=0,temp; memset(vis,0,sizeof(vis)); vis[0]=1; for(int i=0;i<N;i++) {low[i]=map[0][i];} //printf("low %lf \n",low[i]);} for(int i=0;i<N;i++){ temp=INF; for(int j=0;j<N;j++){ if(!vis[j]&&low[j]<temp) temp=low[k=j]; } // printf("***%d %lf ",temp,min); if(temp==INF){ if(flot==N)printf("%.1lf\n",min*100); else puts("oh!"); break; } min+=temp; flot++; vis[k]=1; for(int j=0;j<N;j++){ if(!vis[j]&&low[j]>map[k][j]) low[j]=map[k][j]; } } } int main(){ int T; int dx[MAXN],dy[MAXN]; scanf("%d",&T); while(T--){ for(int i=0;i<MAXN;i++) for(int j=0;j<MAXN;j++) map[i][j]=INF; scanf("%d",&N); for(int i=0;i<N;i++) scanf("%d%d",&dx[i],&dy[i]); for(int i=0;i<N;i++) for(int j=i+1;j<N;j++){ double dis=fd(dx[i],dy[i],dx[j],dy[j]); //printf("### %d %d %lf ",i,j,dis); if(dis<map[i][j]&&dis>=10&&dis<=1000) map[i][j]=map[j][i]=dis; } /*for(int i = 0; i < N; ++i) printf("%lf\n", map[0][i]);*/ prime(); } return 0; }
相关文章推荐
- Acegi授权策略和保护web资源
- poj 1182 深入并查集
- java线程池ThreadPoolExecutor原理及使用
- Swift开发教程--有关图片处理的一些有用函数
- java 环境变量配置
- C++_重载运算符<< ostream流重载注意事项_使自定义数据可以用cout输出
- 数据结构(26)二叉树
- Merge into的使用详解-你Merge了没有【转】
- PAT 1044. Shopping in Mars (25)
- 2015/08/11博客园页面(自身)
- WebSocket在java Tomcat中实现
- UI021---UITableView数据刷新
- 7种查找算法解析
- 好看的dialog,sweet Alert Dialog 导入Android Studio
- svn自动提交WEB应用代码
- 获得Android设备的唯一序列号
- 进程和线程最生动的理解
- 记录贴--Office 2016激活
- 好看的dialog,sweet Alert Dialog 导入Android Studio
- IOS UITableView索引排序功能