1570: [JSOI2008]Blue Mary的旅行|网络流

据说这题的思路挺正常,然而直接没有向拆点的方面想QAQ 可能是做题太少见识太少的原因吧
然而每天只能走一班飞机所以显然要拆点,把每个点拆成 M 个点, M 是天数的上界,极限情况应该是 n+T
因为要求的是最少的天数可以动态加边一直跑网络流,对于原图中的边 (u,v) 连一条从今天的 u 走到明天的 v 的边,还要把前一天的点和后一天的点都连一遍边,然后跑网络流看当前流量是否 T

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<complex>
#include<queue>
#include<map>
#include<set>
#define N 300005
using namespace std;
int sc()
{
    int i=0; char c=getchar();
    while( c>'9' || c<'0' ) c=getchar();
    while( c>='0' && c<='9' )i=i*10+c-'0',c=getchar();
    return i;
}
int dis[N],q[N];
int x[N],y[N],z[N];
int head[N],nxt[N],lst[N],c[N];
int n,m,t,A,ans,S,T,tot=1;
void insert(int x,int y,int z)
{
    lst[++tot]=y;nxt[tot]=head[x];head[x]=tot;c[tot]=z;
    lst[++tot]=x;nxt[tot]=head[y];head[y]=tot;c[tot]=0;
}
bool BFS()
{
    for(int i=1;i<=T;i++)dis[i]=0;
    dis[q[1]=S]=1;
    for(int l=1,r=2;l<r;l++)
    {
        int x=q[l];
        for(int i=head[x];i;i=nxt[i])
            if(c[i]&&!dis[lst[i]])
                dis[q[r++]=lst[i]]=dis[x]+1;
    }
    return dis[T];
}
int dfs(int x,int f)
{
    if(x==T)return f;
    int ww=0,w;
    for(int i=head[x];i;i=nxt[i])
        if(c[i]&&dis[lst[i]]==dis[x]+1)
        {
            w=dfs(lst[i],min(f-ww,c[i]));
            c[i]-=w,c[i^1]+=w,ww+=w;
            if(ww==f)return ww;
        }
    if(!ww)dis[x]=0;
    return ww;
}
int main()
{
    n=sc();m=sc();t=sc();A=n+t;S=1;
    for(int i=1;i<=m;i++)
        x[i]=sc(),y[i]=sc(),z[i]=sc();
    for(int i=1;i<=A;i++)
    {
        for(int j=1;j<=m;j++)
            insert((x[j]-1)*A+i,(y[j]-1)*A+i+1,z[j]);
        for(int j=1;j<=n;j++)
            insert((j-1)*A+i,(j-1)*A+i+1,1e9);
        T=(n-1)*A+i+1;
        while(BFS())ans+=dfs(S,1e9);
        if(ans>=t)
        {
            printf("%d",i);
            return 0;
        }
    }
}

你可能感兴趣的:(网络流)