Time Limit: 3000MS | Memory Limit: 30000K | |
Description
Input
Output
Sample Input
1 3 3 1 2 3 1 3 4 2 3 5
Sample Output
Scenario #1: 4
Source
其实这个题看了好久都没搞懂意思,然后找了找博客原来就是给定n个站点(就这样理解吧),m条路,两个站点之间有且只有一条路,每条路都有一个最大载重量,求整个路径组成的图中的最大的承重;比如,1到2之间的载重是3,超过3便不能从这条路上过,而1到3之间的载重是4,这时已经将图连接起来了,所以最大值是4,如果选1->2->3,则1、2之间的路就不能过重量为5的升降机;
这样,就相当于求一个最大生成树的权值最小的那条边,不过用生成树的方法不是超时就RE,只好用最短路中的一个算法解决了,我们看,既然dijkstra是求单源的最短路,d[i]存储的是从起始点到i点的最短路,那么我们就用它来存起始点到i点权值最小的那个;这样答案不就出来了;想想看,这道题逻辑性很强,求能承载的最大重量实际上是求整个联通图中权值最小的,就像短板原理--能装多少水取决于最短的那块木板;
Kruskal生成树:RE,数组开大了又会超时;
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=1000+10; struct node { int u,v,w; }a[N]; int n,m,f[N]; int find(int x) { return f[x]==-1?x:f[x]=find(f[x]); } int cmp(node a,node b) { return a.w>b.w; } int ks(int n,int m) { for(int i=0;i<m;i++) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); sort(a,a+m,cmp); int minn=10000000; memset(f,-1,sizeof(f)); for(int i=0;i<m;i++) { int x=find(a[i].u); int y=find(a[i].v); if(x!=y) { minn=min(minn,a[i].w); f[x]=y; } if(find(1)==find(n)) break; } return minn; } int main() { int t; scanf("%d",&t); int t1=t; while(t--) { memset(a,0,sizeof(a)); scanf("%d%d",&n,&m); int x=ks(n,m); printf("Scenario #%d:\n%d\n",t1-t,x); } return 0; }
#include<cstdio> #include<cmath> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N=1005; int w[N][N],v[N],d[N],n,m,t,t1; void dijkstra() { int a,b,c,i,j; memset(w,0,sizeof(w)); for(i=1; i<=m; i++) { scanf("%d%d%d",&a,&b,&c); w[a][b]=w[b][a]=c; } memset(v,0,sizeof(v)); for(i=1; i<=n; i++) d[i]=w[1][i]; for(i=1;i<=n;i++) { int x,m=-1; for(j=1;j<=n;j++) if(!v[j]&&d[j]>m) m=d[x=j]; v[x]=1; for(j=1;j<=n;j++) if(!v[j] && d[j]<min(d[x],w[x][j])) d[j]=min(d[x],w[x][j]); } printf("Scenario #%d:\n",t1-t); printf("%d\n\n",d[n]); } int main() { scanf("%d",&t); t1=t; while(t--) { scanf("%d%d",&n,&m); dijkstra(); } return 0; }