zoukankan      html  css  js  c++  java
  • 51nod 1171 大灾变

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1757

    二分答案mid

    避难所拆为mid个点

    每个避难所的第一个点向第二个点,第二个点向第三个点……连inf边

    每个点向汇点连流量为1的边

    枚举能在mid时间内到达避难所i的点j,假设时间为t,由点j向点i的第t个点连流量为1的边

    源点向每个非避难所节点连流量为1的边

    最大流判断能否==n-m

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 2001
    using namespace std;
    int n,m,p,src,decc,cnt;
    int front[N*200],nxt[N*500],to[N*500],cap[N*500],tot;
    int dis[41][N];
    int cur[N*200],lev[N*200];
    bool vis[N*200],safe[N];
    const int inf=2e9;
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=0;
    }
    void build(int mid)
    {
        memset(front,0,sizeof(front));
        tot=1;    decc=n+m*mid+1;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<mid;j++) 
             add(n+mid*(i-1)+j,n+mid*(i-1)+j+1,inf);
            for(int j=1;j<=n;j++)
                if(!safe[j] && dis[i][j]<=mid) 
                    add(j,n+mid*(i-1)+dis[i][j],1);
        }
        for(int i=n+1;i<decc;i++) add(i,decc,inf);
        for(int i=1;i<=n;i++) if(!safe[i]) add(src,i,1);
    }
    bool bfs()
    {
        for(int i=0;i<=decc;i++) cur[i]=front[i],lev[i]=-1;
        queue<int>q;
        vis[src]=true;
        lev[src]=0;
        q.push(src);
        int now;
        while(!q.empty())
        {
            now=q.front();
            q.pop(); vis[now]=false;
            for(int i=front[now];i;i=nxt[i])
                if(lev[to[i]]==-1 && cap[i]>0)
                {
                    lev[to[i]]=lev[now]+1;
                    if(to[i]==decc) return true;
                    if(!vis[to[i]])
                    {
                        vis[to[i]]=true;
                        q.push(to[i]);
                    }
                }
        }
        return false;
    }
    int dinic(int now,int flow)
    {
        if(now==decc) return flow;
        int rest=0,delta;
        for(int & i=cur[now];i;i=nxt[i])
            if(lev[to[i]]>lev[now] && cap[i]>0)
            {
                delta=dinic(to[i],min(cap[i],flow-rest));
                if(delta)
                {
                    cap[i]-=delta,cap[i^1]+=delta;
                    rest+=delta; 
                    if(rest==flow) break;
                }
            }
        if(rest!=flow) lev[now]=-1;
        return rest;
    }
    bool check(int mid)
    {
        build(mid);
        int now=0;
        while(bfs()) now+=dinic(src,inf);
        if(now==n-m) return true;
        return false;
    }
    void dfs(int x,int f,int s)
    {
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=f)
            {
                dis[s][to[i]]=dis[s][x]+1;
                dfs(to[i],x,s);
            }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int u,v;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v,0);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&u);
            safe[u]=true;
            dfs(u,0,i);
        }
        int l=1,r=n+1,mid,ans;
        while(l<=r)
        {
            mid=l+r>>1;
            if(check(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d",ans);
    }
    基准时间限制:3 秒 空间限制:262144 KB 分值: 160 难度:6级算法题
     收藏
     关注
    死亡之翼降临了!艾泽拉斯大陆的子民们必须逃出他的魔爪!
    艾泽拉斯的结构是一棵树,这棵树上的一些节点是地精建造的通往地下避难所的洞口。
    除了这些洞口之外,树上的每个节点上都有一个种族,每个种族通过树上的一条边都需要一个单位时间。
    因为地精比较矮小,所以洞口很窄,每个单位时间只能让一个种族通过,但是一个单位时间内的一个节点上可以存在多个种族。
    地精们需要你求出最少需要多少单位时间才能让所有种族躲进地下避难所。
    【注意题目有修改,洞口不一定是叶子节点】
    Input
    第1行两个整数n(n<=2000)和m(m<=40)表示节点个数和洞口个数
    接下来n-1行每行两个整数表示树上的每一条边
    第n+1行m个整数表示所有洞口的编号,保证洞口是叶子节点
    Output
    一个整数t表示让所有种族躲进地下避难所的最少时间
    Input示例
    6 2
    1 2
    1 3
    1 4
    1 5
    5 6
    3 6
    Output示例
    3
  • 相关阅读:
    c11---位运算相关
    c10---多文件开发
    C9---include,编译
    c8---递归
    c7---函数
    c6----函数的声明和实现
    c5
    Arm 环境上面libgdiplus的简单安装配置
    批量查找可执行文件目录的简单方法
    Android常用工具类
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7512407.html
Copyright © 2011-2022 走看看