暑期个人赛--第八场--B(关于手写队列的启示+题目有坑)
2014-07-31 15:32
190 查看
468. 小妹妹送快递
时间限制 1000 ms 内存限制 65536KB
题目描述
Mays王国的女王大人每天过着自由自在的生活,她最大的乐趣就是给邻国的帅气王子写信。但是最近,Mays王国的叔叔们变得很无聊,他们知道女王大人每次都把信委托给皇家小妹妹快递公司的小妹妹们,于是叔叔们给每一条路都设立了路障,只有小妹妹们给他们表演节目才会让小妹妹们过去。在每一个路障,都有不同数量的叔叔,只有表演的小妹妹的数量不少与叔叔的数量的时候叔叔才会放她们过去。
为了节省开销,小妹妹快递公司希望派最少的小妹妹把女王大人的信件送到。请你告诉他们需要派几个小妹妹。
输入格式
输入第一行为数据组数T(T<=10),接下来T组数据,每组第一行为n,m,,2<=n<=10000,1<=m<=100000,表示Mays王国的道路由n个节点组成,接下来m行,每行一组u,v,c表示连接节点u,v的一条无向道路,且路障上有c个叔叔,1<=u,v<=n,0<=c<=100。女王大人和皇家小妹妹快递公司都在节点1,帅气的邻国王子住在节点n。
输出格式
每组数据输出一个数字,表示小妹妹快递公司最少需要派出的小妹妹数量。如果无论派出多少小妹妹都无法把信送到帅气的邻国王子手里,输出"shimatta!"。
输入样例
1 3 3 1 2 1 2 3 1 1 3 3
输出样例
1
赛中提交:RE RE RE RE WA WA
赛后AC:Y
总结&反省:
(1)赛中的时候RE了好多次,还有之前的一道也是用了静态邻接链表+SPFA的题目,也是RE
这两次都是先一直以为是存边的G开小了,结果改了边一直没过,最后是改了存点的maxn过了
后来也一直没有搞清楚原因,直到问了某翔,他指出是队列数组超了,
原因是,假设某个点向外一共连有e条边,那么当我们每选中那e个点中的一个,都会让这个入队一次
也就是说入队的总点数是maxe,所以最保险的是把队列数组开得比边的最大数量大一点
(2)其次是这个题目的一个大坑,当所有的路的权值都为0时,这个时候spfa输出的值是0....
但是你还是需要一个人送出去的对不对~!?!?!!?!?
(3)说说思路,其实在赛中思路是已经自己给出来了的,
那就是将松弛的对象(d[i]原来表示某点都达源点的最短距离)改成所选择路径上所有边中的最大权值
也就是说“d[i]表示从i到达源点的路径上所有边中的最大权值”
下面是AC代码:
#include <iostream> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string> #include <vector> #include <list> #include <map> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <numeric> #include <functional> #define maxn 10005 #define maxe 200005 using namespace std; struct edge{ int to,next,cost; }; edge G[maxe]; int si,head[maxn],vis[maxn]; int n,m; int dis[maxn]; int q[maxe]; void add_edge(int u,int v,int cost) { G[si].to=v; G[si].next=head[u]; G[si].cost=cost; head[u]=si++; } void spfa(int start) { for(int i=1;i<=n;i+=1){ dis[i]=999999999; } int i,hea=0,tail=1; q[hea]=start; dis[start]=0; vis[start]=1; while(hea<tail){ int from=q[hea++]; vis[from]=0; for(int i=head[from];i!=-1;i=G[i].next){ int to=G[i].to; if(dis[to]>max(dis[from],G[i].cost)){ dis[to]=max(dis[from],G[i].cost); if(!vis[to]){ q[tail++]=to; vis[to]=1; } } } } if(!dis ){ printf("shimatta!\n"); } else{ printf("%d\n",dis ); } } int main() { int t; scanf("%d",&t); while(t--){ bool flag=false; si=0; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); scanf("%d %d",&n,&m); for(int i=0;i<m;i+=1){ int u,v,cost; scanf("%d %d %d",&u,&v,&cost); if(cost){ flag=true; } add_edge(u,v,cost); add_edge(v,u,cost); } if(!flag){ printf("1\n"); } else{ spfa(1); } } return 0; }
相关文章推荐
- 暑期个人赛--第六场--D(包含手写邻接链表模板~!!)
- 暑期个人赛--第八场--C(自己坑自己~!!!!)
- 关于单调队列的个人理解
- 暑期个人赛--第八场--D
- 关于栈和队列的三个题目
- 关于微软面试100题系列中两道题目的个人解法
- 暑期个人赛--第八场--A
- 关于C++队列操作(并附上一道Boring题目)
- 关于09网易软测题目个人测试思路总结
- 关于栈和队列的题目总结
- (待切,标记上)暑期个人赛--第八场--E
- 关于队列的个人见解
- 关于java的编码问题,个人的一个补充
- 虽然没有礼品,希望大家能看看这几个关于指针的小题目
- 关于Visual InterDev 6.0 调试ASP工程的个人方法。
- 一间公司关于VS.NET的面试题目
- 关于堆栈与队列使用的小思考(1)
- 《关于个人承接项目的注意事项》读后感
- 谈点关于SmartClient的个人看法。
- [软件人生]关于个人所得税的讨论