1. 程式人生 > >洛谷 P10P1343 地震逃生 改錯

洛谷 P10P1343 地震逃生 改錯

無法 break use 發生 最大 print 現在 int 網絡流

P1343 地震逃生

題目描述

汶川地震發生時,四川**中學正在上課,一看地震發生,老師們立刻帶領x名學生逃跑,整個學校可以抽象地看成一個有向圖,圖中有\(n\)個點,\(m\)條邊。1號點為教室,\(n\)號點為安全地帶,每條邊都只能容納一定量的學生,超過樓就要倒塌,由於人數太多,校長決定讓同學們分成幾批逃生,只有第一批學生全部逃生完畢後,第二批學生才能從1號點出發逃生,現在請你幫校長算算,每批最多能運出多少個學生,\(x\)名學生分幾批才能運完。

輸入輸出格式

輸入格式:

第一行3個整數\(n,m,x(x<2^{31},n<=200,m<=2000)\);以下\(m\)行,每行三個整數\(a,b,c\)

描述一條邊,分別代表從\(a\)點到\(b\)點有一條邊,且可容納\(c\)名學生。

輸出格式:

兩個整數,分別表示每批最多能運出多少個學生,\(x\)名學生分幾批才能運完。如果無法到達目的地(\(n\)號點)則輸出“\(Orz\) \(Ni\) \(Jinan\) \(Saint\) \(Cow!\)


很明顯網絡流的裸題。

前幾天看到對前向星用\(x\) \(nor\) 1\(找反邊,覺得很方便,遂用一下,用想到很久沒打\)dinic$了,就決定打打(以前都是偷懶打EK的)

不過這樣找反邊\(head\)最開始時得賦\(-1\),而且邊的邊界也是-1

因為
\(x\) \(nor\) \(1=x+1\)

\(x\)為偶
\(x\) \(nor\) \(1=x-1\)\(x\)為奇

得用上0

然後我.....

技術分享圖片

我是得多智障才這樣,居然樣例還對了...

還有一點,最後算答案是\((ans-1)/\)最大流\(+1\)

我沒給那個\(ans\)減一下


code:

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N=204;
const int M=2004;
const int inf=0x3f3f3f3f;
struct Edge
{
    int w,to,next;
}edge[M*2];
struct node
{
    int cnt,u;
}S[N];
int n,m,X,cnt=-1,head[N];
int top=0;
void push(int cnt0,int u0) {S[++top].cnt=cnt0,S[top].u=u0;}
void pop() {top--;}
int read()
{
    int x=0;char c=getchar();
    while(c<‘0‘||c>‘9‘) c=getchar();
    while(c>=‘0‘&&c<=‘9‘) {x=x*10+c-‘0‘;c=getchar();}
    return x;
}

void add(int u,int v,int w)
{
    edge[++cnt].next=head[u],edge[cnt].to=v,edge[cnt].w=w,head[u]=cnt;
    edge[++cnt].next=head[v],edge[cnt].to=u,edge[cnt].w=0,head[v]=cnt;
}
int dep[N],used[N],ans=0;
queue <int > q;
bool bfs()
{
    memset(dep,0,sizeof(dep));
    while(!q.empty()) q.pop();
    q.push(1);dep[1]=1;
    while(!q.empty()&&q.front()!=n)
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to,w=edge[i].w;
            if(!dep[v]&&w)
            {
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }
    return !q.empty();
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read(),m=read(),X=read();
    int u,v,w;
    for(int i=1;i<=m;i++)
    {
        u=read(),v=read(),w=read();
        add(u,v,w);
    }
    while(bfs())
    {
        memset(used,0,sizeof(used));
        top=0;
        push(head[1],1);
        while(top)
        {
            if(S[top].u==n)
            {
                int m_min=inf,id;
                for(int i=2;i<=top;i++)
                    if(edge[S[i].cnt].w<m_min)
                    {
                        m_min=edge[S[i].cnt].w;
                        id=i;
                    }
                ans+=m_min;
                for(int i=2;i<=top;i++)
                {
                    edge[S[i].cnt].w-=m_min;
                    edge[(S[i].cnt)^1].w+=m_min;
                }
                used[n]=0;
                top=max(0,id-1);
            }
            else
            {
                int u=S[top].u;
                for(int i=head[u];i!=-1;i=edge[i].next)
                {
                    int v=edge[i].to,w=edge[i].w;
                    if(!used[v]&&w&&dep[v]==dep[u]+1)
                    {
                        used[v]=1;
                        push(i,v);
                        break;
                    }
                }
                if(S[top].u==u) top--;
            }
        }
    }
    if(ans==0) {printf("Orz Ni Jinan Saint Cow!\n");return 0;}
    printf("%d %d\n",ans,(X-1)/ans+1);
    return 0;
}

2018.5.20

洛谷 P10P1343 地震逃生 改錯