Gym

来源:互联网 发布:windows ftp登录命令 编辑:程序博客网 时间:2024/06/11 04:06

题目链接:gym 101617H


题目大意:现在有n个房间,m扇门,每扇门上连接a,b两个房间(注意只能从a到b),上面有一个最大值max和最小值min,人身上有一个编号,只有当编号位于[min,max]时,人才能通过那扇门。给出起点和终点,求一共有多少个数字,要求当人身上的编号为这些数字时人能从起点到终点。


题目分析:因为最好到达终点的区间肯定是前面出现过的,区间的断点组合而成的,所以我们可以直接对门上的断点来排序并离散化,然后枚举两个相邻的端点判断这个区间能否最后到达终点来产生贡献。

参考资料:大神博客


代码:

#include <queue>#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int maxn=5000+100;int n,m,k,s,t,tot;bool vis[maxn];int head[maxn],a[maxn*2];struct node{    int v,next,l,r;}edge[maxn];void init(){    tot=0;    memset(head,-1,sizeof(head));}void addEdge(int u,int v,int l,int r){    edge[tot].v=v;    edge[tot].l=l;    edge[tot].r=r;    edge[tot].next=head[u];    head[u]=tot++;}//判断是否存在从起点到终点的路径bool dfs(int p,int l,int r){    vis[p]=true;    if(p==t)    return true;    for(int i=head[p];i!=-1;i=edge[i].next){        int v=edge[i].v;        if(vis[v])  continue;        if(edge[i].l<=l&&r<=edge[i].r&&dfs(v,l,r)){            return true;        }    }    return false;}int main(){//    freopen("in.txt","r",stdin);    while(~scanf("%d%d%d",&n,&m,&k))    {        init();        scanf("%d%d",&s,&t);        for(int i=0;i<m;i++){            int u,v,l,r;            scanf("%d%d%d%d",&u,&v,&l,&r);            a[i<<1]=l;            //注意这里区间要转化成左闭右开            a[i<<1|1]=r+1;            addEdge(u,v,l,r);        }        //排序        sort(a,a+2*m);        int ans=0;        //去重        int num=unique(a,a+2*m)-a;        for(int i=1;i<num;i++){            memset(vis,0,sizeof(vis));            if(dfs(s,a[i-1],a[i]-1)){                //这样记录答案就不会产生重叠                ans+=a[i]-a[i-1];            }        }        printf("%d\n",ans);    }    return 0;}


原创粉丝点击