Hrbust 2206 The Smallest Oil Tank【二分+Prim】卡内存= =

来源:互联网 发布:网络摄像头远程监控 编辑:程序博客网 时间:2024/06/07 04:42

The Smallest Oil TankTime Limit: 10000 MSMemory Limit: 65536 KTotal Submit: 16(4 users)Total Accepted: 2(2 users)Rating: Special Judge: NoDescription

That’s great ! LPJ get married! He will take his wife on a honeymoon by driving. Now, he want to leave from home to Moscow. But his oil tank is limited and he doesn’t have enough oil to Moscow. Luckily,there are many gas stations.

There are n gas stations numbered from 0 to n-1. The 0 station is LPJ’s home and n-1 station is Moscow.  He knows the oil used from one gas station to another.  He can fill the tank at every gas station.

But the problem is coming. He want to take a car with the smallest oil tank.Please help LPJ get the smallest oil tank.

Input

There are multiple test cases.

Each test case contains two postive integers (n,m) separated by a space in one line. The n is the number of gas station.

The next m line ,each line contains three postive integers (u,v,w). It means that there is one road between u and v gas station using w Liter.

   There are at least one road from 0 to n-1 gas station.

The input will be terminated by the end of input file.

2<=n<=4,000

1<=m<=10,000,000

1<=w<=10,000,000

Output

For each test case ,output the smallest oil tank.

Sample Input
3 2
0 1 2
1 2 3
3 3
0 1 2
1 2 3
1 2 1

Sample Output
3
2

SourceCPC23 2014-6AuthorACgege

题目大意:


现在希望设定一辆车的油箱体积,想要从城市1到城市n,路上不能加油,每到一个城市都可以进行加油。

问我们设定的最小油箱体积是多少,使得我们可以从1遍历到城市n.


思路:


我们二分最大边权,即我们二分的就是当前油箱体积。

如果小于等于油箱体积的边我们建图,然后跑最小生成树等判断连通的算法,只要判断点1和点n是否连通即可。



很明显,直接存边跑个排序的话时间复杂度巨高,再套个二分的话时间复杂度是O(mlogm+m*log(maxnw));

而我们跑Prim+二分的话时间复杂度为O(n*n*log(maxnw));

其实两者的时间复杂度都是差不太多的,只不过第一种方法用结构体存m条边的话空间复杂度需要O(m*3)约为3e7.

而第二种方法存图的空间复杂度只要O(n^2).约为1.6e7.内存相差一倍。

这个题卡了内存,第一种方法存图会MLE....


用第二种方法跑了9200+ms= =.如果TLE了可以再套个堆优化。


Ac代码:

#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define inf 0x3f3f3f3fint a[4002][4002];int vis[4002];//用来表示这个点有没有遍历的到.int  dis[4002];int n,m;int Slove(int mid){    memset(vis,0,sizeof(vis));    int i,j,k,min;    for(i=2;i<=n;i++)    {        if(a[1][i]<=mid)dis[i]=a[1][i];        else dis[i]=inf;    }    vis[1]=1;    for(i=2;i<=n;i++)//经过N次遍历一定能遍历所有的点 也就是完成了最终目标.    {        min=inf;        for(j=1;j<=n;j++)        {            if(vis[j]==0 &&dis[j]<min)            {                min=dis[j];                k=j;            }        }        if(min==inf||min>mid)            break;        vis[k]=1;        for(j=2;j<=n;j++)        {            if(a[k][j]>mid)continue;            if(vis[j]==0 &&dis[j]>a[k][j])                dis[j]=a[k][j];        }//更新最优解.    }    if(dis[n]!=inf)return 1;    else return 0;}int main(){    while(~scanf("%d%d",&n,&m))    {        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++)            {                a[i][j]=inf;            }        }        int maxn=0;        for(int i=0;i<m;i++)        {            int x,y,w;            scanf("%d%d%d",&x,&y,&w);x++,y++;            a[x][y]=min(a[x][y],w);            a[y][x]=min(a[y][x],w);            maxn=max(maxn,w);        }        int ans=-1;        int l=1;        int r=maxn;        while(r-l>=0)        {            int mid=(l+r)/2;            if(Slove(mid)==1)            {                ans=mid;                r=mid-1;            }            else l=mid+1;        }        printf("%d\n",ans);    }}





原创粉丝点击