zoukankan      html  css  js  c++  java
  • P1343 地震逃生

    题目描述

    汶川地震发生时,四川**中学正在上课,一看地震发生,老师们立刻带领x名学生逃跑,整个学校可以抽象地看成一个有向图,图中有n个点,m条边。1号点为教室,n号点为安全地带,每条边都只能容纳一定量的学生,超过楼就要倒塌,由于人数太多,校长决定让同学们分成几批逃生,只有第一批学生全部逃生完毕后,第二批学生才能从1号点出发逃生,现在请你帮校长算算,每批最多能运出多少个学生,x名学生分几批才能运完。

    输入输出格式

    输入格式:

    第一行3个整数n,m,x(x<2^31,n<=200,m<=2000);以下m行,每行三个整数a,b,c(a1,a<>b,0描述一条边,分别代表从a点到b点有一条边,且可容纳c名学生。

    输出格式:

    两个整数,分别表示每批最多能运出多少个学生,x名学生分几批才能运完。如果无法到达目的地(n号点)则输出“Orz Ni Jinan Saint Cow!”

    输入输出样例

    输入样例#1:
    6 7 7
    1 2 1
    1 4 2
    2 3 1
    4 5 1
    4 3 1
    3 6 2
    5 6 1
    输出样例#1:
    3 3

    说明

    【注释】

    比如有图

    1 2 100

    2 3 1

    100个学生先冲到2号点,然后1个1个慢慢沿2-3边走过去

    18神牛规定这样是不可以的……

    也就是说,每批学生必须同时从起点出发,并且同时到达终点

    来一发Dinic。

    这题比较少,我们想一下,如果要输送学生,我们只要找出每次可以通过的最大的学生数量就好。

    然后用一点贪心的原理,每次都去用最大的输送方案输送学生(废话。。)

    只要最大流不为0就一定能输送完成

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<queue>
      6 #include<algorithm>
      7 #define lli long long int 
      8 using namespace std;
      9 const int MAXN=300001;
     10 const int maxn=0x7fffff;
     11 void read(int &n)
     12 {
     13     char c='+';int x=0;bool flag=0;
     14     while(c<'0'||c>'9')
     15     {c=getchar();if(c=='-')flag=1;}
     16     while(c>='0'&&c<='9')
     17     {x=(x<<1)+(x<<3)+c-48;c=getchar();}
     18     flag==1?n=-x:n=x;
     19 }
     20 struct node
     21 {
     22     int u,v,flow,cap,nxt;
     23 }edge[MAXN];
     24 int head[MAXN];
     25 int num=0;
     26 int n,m,S,T,x;
     27 int dis[MAXN];
     28 int vis[MAXN];
     29 int cur[MAXN];
     30 void add_edge(int x,int y,int z)
     31 {
     32     edge[num].u=x;
     33     edge[num].v=y;
     34     edge[num].cap=z;
     35     edge[num].flow=0;
     36     edge[num].nxt=head[x];
     37     head[x]=num++;
     38 }
     39 bool bfs(int bg,int ed)
     40 {
     41     memset(dis,-1,sizeof(dis));
     42     queue<int>q;
     43     q.push(bg);
     44     dis[bg]=0;
     45     while(!q.empty())
     46     {
     47         int p=q.front();
     48         q.pop();
     49         for(int i=head[p];i!=-1;i=edge[i].nxt)
     50         {
     51             if(dis[edge[i].v]==-1&&edge[i].cap>edge[i].flow)
     52             {
     53                 vis[edge[i].v]=1;
     54                 dis[edge[i].v]=dis[edge[i].u]+1;
     55                   q.push(edge[i].v);            
     56             }
     57         }
     58     }
     59     if(dis[ed]==-1)
     60         return 0;
     61     else return 1;
     62 }
     63 int dfs(int now,int a)// a:所有弧的最小残量 
     64 {
     65     if(now==T||a<=0)
     66         return a;
     67         
     68     int flow=0,f;
     69     for(int i=head[now];i!=-1;i=edge[i].nxt)
     70     {
     71         if(dis[now]+1==dis[edge[i].v]&&edge[i].cap-edge[i].flow>0)
     72         {
     73             f=dfs(edge[i].v,min(a,edge[i].cap-edge[i].flow));
     74             edge[i].flow+=f;
     75             edge[i^1].flow-=f;
     76             flow+=f;
     77             a-=f;
     78             if(a<=0)break;
     79         }
     80     }
     81     return flow;
     82 }
     83 void Dinic(int S,int T)
     84 {
     85     int ansflow=0;
     86     int cs=0;
     87     int maxflow=0;
     88     for(int i=1;i<=n;i++)
     89             cur[i]=head[i];
     90     while(bfs(S,T))
     91     {
     92         int p=dfs(S,maxn);
     93         cs++;
     94         ansflow+=p;
     95         maxflow=max(maxflow,p); 
     96     }// 求出层级
     97     if(ansflow==0)
     98         printf("Orz Ni Jinan Saint Cow!");
     99     else 
    100         printf("%d %d",ansflow,(x%ansflow)==0?(x/ansflow):(x/ansflow+1));
    101         
    102     //printf("%d",ansflow);
    103     
    104 }
    105 int main()
    106 {
    107     scanf("%d%d%d",&n,&m,&x);
    108     //read(n);read(m);read(x);
    109 //    swap(n,m);
    110     S=1;T=n;
    111    // read(S);read(T);
    112     for(int i=1;i<=n;i++)
    113         head[i]=-1;
    114     for(int i=1;i<=m;i++)
    115     {
    116         int x,y,z;
    117         //read(x);read(y);read(z);
    118         scanf("%d%d%d",&x,&y,&z);
    119         add_edge(x,y,z);
    120         add_edge(y,x,0);
    121     }
    122     Dinic(S,T);
    123     return 0;
    124 }
  • 相关阅读:
    OO第四次暨期末总结
    OO第九到十一次作业小结
    OO第五到七次作业小结
    OO前三次作业阶段小结
    数据预处理相关
    Latex+VScode安装
    python学习网站+查询网站
    arcgis画图中添加带箭头的直线
    在ArcGIS 中标注中竖排文字
    vs2015使用fopen时遇到unsafe问题
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/7146094.html
Copyright © 2011-2022 走看看