HDU 1839 Delay Constrained 带限制最短路:二分下限

来源:互联网 发布:网络交换机cad图标 编辑:程序博客网 时间:2024/06/06 02:26

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=3631

题意

金矿位置在1号位置,加工厂在n号位置,从1到n的路中有一些中转结点,任意两个点最多只有一条路,每条路有两个属性:容量和时间,一条从1~n的路径的容量由路径中最小边容量确定,即路径的容量等于这条路径中边的容量最小的那条边。通过路径时间为路径中所有边时间之和。选择一条路线从金矿中提取金矿到工厂的时间不能超过T,且容量最大。

思路

题目中说了,至少有一条路满足时间限制,假设最小边的权值t,图中小于t的边都删去,那么t越大,删除的边越少,甚至可以大到不删边。如果为t时满足了时间限制,大于等于t时也会满足,所有需要缩小t,二分枚举t,跑最短看是否符合时间小于等于T。

#include<cstdio>#include<queue>#include<iostream>#include<vector>#include<map>#include<cstring>#include<string>#include<set>#include<stack>#include<algorithm>#define cle(a) memset(a,0,sizeof(a))#define inf(a) memset(a,0x3f,sizeof(a))#define ll long long#define Rep(i,a,n) for(int i=a;i<=n;i++)using namespace std;#define INF2 9223372036854775807llconst int INF = ( 2e9 ) + 2;const ll maxn = 1e4+10;const int maxm = 5e4+10;struct edge{    int v,c,t,next;}e[maxm*2];struct Edge{    int u,v,c,t;};struct node{    int u,d;    bool operator < (const node &b)const    {        return d>b.d;    }};vector<Edge> E;int head[maxn],vis[maxn],d[maxn];int tot;void addedge(int u,int v,int c,int t){    e[tot].v=v;    e[tot].c=c;    e[tot].t=t;    e[tot].next=head[u];    head[u]=tot++;}int dijkstra(int s,int n){    for(int i=1;i<=n;i++)d[i]=INF;    d[s]=0;    memset(vis,0,sizeof(vis));    priority_queue<node> q;    q.push(node{s,0});    while(!q.empty())    {        node temp=q.top();q.pop();        int u=temp.u;        if(vis[u])continue;        vis[u]=1;        for(int i=head[u];i!=-1;i=e[i].next)        {            int v=e[i].v;            int w=e[i].t;            if(d[v]>d[u]+w)            {                d[v]=d[u]+w;                q.push(node{v,d[v]});            }        }    }    return d[n];}bool check(int t,int T,int n){    memset(head,-1,sizeof(head));    tot=0;    for(int i=0,L=E.size();i<L;i++)    {        if(E[i].c>=t)        {            addedge(E[i].u,E[i].v,E[i].c,E[i].t);            addedge(E[i].v,E[i].u,E[i].c,E[i].t);        }    }    return dijkstra(1,n)<=T;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m,T;        scanf("%d%d%d",&n,&m,&T);        E.clear();        for(int i=0;i<m;i++)        {            int u,v,c,t;            scanf("%d%d%d%d",&u,&v,&c,&t);            E.push_back(Edge{u,v,c,t});        }        int l=1,r= 2000000000; //最大化最小值         int ans;        while(l<r)        {            int mid=(l+r)>>1;            if(check(mid,T,n))            l=mid+1;            else            r=mid;        }        printf("%d\n",r-1);    }}
阅读全文
0 0
原创粉丝点击