3931: [CQOI2015]网络吞吐量

这是一道水题。。
题意有点羞涩难懂,自己慢慢看吧。。
只需要一开始跑最短路然后建图网络流就好了。。
然后呢,最短路可以有多条,一开始我的做法比较傻,开了个数组来存。。
然后时间很慢,空间很大,编译TLE了

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
typedef long long LL;
const LL N=505*2;
const LL M=100005*2;
const LL MAX=1LL<<60;
struct qq{LL x,y,z,last,other;}s[M*2];
LL num,last[N];
LL n,m;
void init (LL x,LL y,LL z)
{
    num++;
    s[num].x=x;s[num].y=y;s[num].z=z;
    s[num].last=last[x];
    last[x]=num;
}
LL tt[N][M];//这个点的最短路都可以从哪些点多来
LL t[N];
priority_queue < pair <LL,LL >,vector<pair<LL,LL> >,greater<pair<LL,LL> > > q;
bool in[N];
void SPFA ()
{
    memset(t,127,sizeof(t));
    memset(in,false,sizeof(in));
    q.push(make_pair(0,1));t[1]=0;in[1]=true;
    while (!q.empty())
    {
        int x=q.top().second;q.pop();
        for (LL u=last[x];u!=-1;u=s[u].last)
        {
            LL y=s[u].y;
            if (t[y]>t[x]+s[u].z)
            {
                t[y]=t[x]+s[u].z;
                tt[y][0]=1;tt[y][1]=x;
                if (in[y]==true) continue;
                in[y]=true;
                 q.push(make_pair(t[y],y));
            }
            else if (t[y]==t[x]+s[u].z)
            {
                tt[y][0]++;
                tt[y][tt[y][0]]=x;
            }
        }
        in[x]=false;
    }
}
void dfs (LL x)
{
    if (x==1) return ;
    if (in[x]==true) return ;
    in[x]=true;
    for (LL u=1;u<=tt[x][0];u++)
    {
        init(tt[x][u]+n,x,MAX);s[num].other=num+1;
        init(x,tt[x][u]+n,0);s[num].other=num-1;
        dfs(tt[x][u]);
    }
}
LL h[N];
LL st1,ed1;
LL Q[N];
bool bt ()
{
    memset(h,0,sizeof(h));
    LL st=1,ed=2;
    h[st1]=1;
    Q[st]=st1;
    while (st!=ed)
    {
        LL x=Q[st];
        for (LL u=last[x];u!=-1;u=s[u].last)
        {
            LL y=s[u].y;
            if (s[u].z>0&&h[y]==0)
            {
                h[y]=h[x]+1;
                Q[ed]=y;
                ed++;
            }
        }
        st++;
    }
    if (h[ed1]!=0) return true;
    return false;
}
LL mymin (LL x,LL y)
{
    return x<y?x:y;
}
LL find (LL x,LL f)
{
    if (x==ed1) return f;
    LL s1=0,t;
    for (LL u=last[x];u!=-1;u=s[u].last)
    {
        LL y=s[u].y;
        if (s[u].z>0&&h[y]==(h[x]+1)&&s1<f)
        {
            t=find(y,mymin(s[u].z,f-s1));
            s1+=t;
            s[u].z-=t;
            s[s[u].other].z+=t;
        }
    }
    if (s1==0) h[x]=0;
    return s1;
}
int main()
{
    num=0;memset(last,-1,sizeof(last));
    scanf("%lld%lld",&n,&m);
    for (LL u=1;u<=m;u++)
    {
        LL x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        init(x,y,z);init(y,x,z);
    }
    SPFA();
    num=0;memset(last,-1,sizeof(last));
    memset(in,false,sizeof(in));
    dfs(n);
    for (LL u=1;u<=n;u++)
    {
        LL a;
        scanf("%lld",&a);
        if (u==1||u==n) continue;
        init(u,u+n,a);s[num].other=num+1;
        init(u+n,u,0);s[num].other=num-1;
    }
    st1=1+n;ed1=n;
    LL ans=0;
    while (bt()==true)
        ans=ans+find(st1,MAX);
    printf("%lld",ans);
    return 0;
}

那这怎么办呢,我们发现,我们并不要存下来,我们只需要在跑完之后看一次就好了。。
于是就有了如下版本,SPFA还是要加堆优化

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define swap(x,y) {int tt=x;x=y;y=tt;}
using namespace std;
typedef long long LL;
const int N=505*2;
const int M=100005;
const LL MAX=1LL<<60;
struct qq{int x,y,last,other;LL z;}s[M*4];
int num,last[N];
int n,m;
void init (int x,int y,LL z)
{
    num++;
    s[num].x=x;s[num].y=y;s[num].z=z;
    s[num].last=last[x];
    last[x]=num;
}
int X[M],Y[M];
LL Z[M];
LL t[N];
priority_queue < pair <LL,int >,vector<pair<LL,int> >,greater<pair<LL,int> > > q;
bool in[N];
void SPFA ()
{
    memset(t,127,sizeof(t));
    memset(in,false,sizeof(in));
    q.push(make_pair(0,1));t[1]=0;in[1]=true;
    while (!q.empty())
    {
        int x=q.top().second;q.pop();
        for (LL u=last[x];u!=-1;u=s[u].last)
        {
            LL y=s[u].y;
            if (t[y]>t[x]+s[u].z)
            {
                t[y]=t[x]+s[u].z;
                if (in[y]==true) continue;
                in[y]=true;
                 q.push(make_pair(t[y],y));
            }
        }
        in[x]=false;
    }
}
void dfs ()
{
    for (int u=1;u<=m;u++)
    {
        if (t[X[u]]+Z[u]==t[Y[u]])
        {
            init(X[u]+n,Y[u],MAX);s[num].other=num+1;
            init(Y[u],X[u]+n,0);s[num].other=num-1;
        }
        swap(X[u],Y[u]);
        if (t[X[u]]+Z[u]==t[Y[u]])
        {
            init(X[u]+n,Y[u],MAX);s[num].other=num+1;
            init(Y[u],X[u]+n,0);s[num].other=num-1;
        }
    }
    /*if (x==1) return ;
    if (in[x]==true) return ;
    in[x]=true;
    for (int u=1;u<=tt[x][0];u++)
    {
        init(tt[x][u]+n,x,MAX);s[num].other=num+1;
        init(x,tt[x][u]+n,0);s[num].other=num-1;
        dfs(tt[x][u]);
    }*/
}
int h[N];
int st1,ed1;
int Q[N];
bool bt ()
{
    memset(h,0,sizeof(h));
    int st=1,ed=2;
    h[st1]=1;
    Q[st]=st1;
    while (st!=ed)
    {
        int x=Q[st];
        for (int u=last[x];u!=-1;u=s[u].last)
        {
            int y=s[u].y;
            if (s[u].z>0&&h[y]==0)
            {
                h[y]=h[x]+1;
                Q[ed]=y;
                ed++;
            }
        }
        st++;
    }
    if (h[ed1]!=0) return true;
    return false;
}
LL mymin (LL x,LL y)
{
    return x<y?x:y;
}
LL find (int x,LL f)
{
    if (x==ed1) return f;
    LL s1=0,t;
    for (int u=last[x];u!=-1;u=s[u].last)
    {
        int y=s[u].y;
        if (s[u].z>0&&h[y]==(h[x]+1)&&s1<f)
        {
            t=find(y,mymin(s[u].z,f-s1));
            s1+=t;
            s[u].z-=t;
            s[s[u].other].z+=t;
        }
    }
    if (s1==0) h[x]=0;
    return s1;
}
int main()
{
    num=0;memset(last,-1,sizeof(last));
    scanf("%d%d",&n,&m);
    for (int u=1;u<=m;u++)
    {
        int x,y;
        LL z;
        scanf("%d%d%lld",&X[u],&Y[u],&Z[u]);
        init(X[u],Y[u],Z[u]);init(Y[u],X[u],Z[u]);
    }
    SPFA();
    num=0;memset(last,-1,sizeof(last));
    dfs();
    for (int u=1;u<=n;u++)
    {
        LL a;
        scanf("%lld",&a);
        if (u==1||u==n) continue;
        init(u,u+n,a);s[num].other=num+1;
        init(u+n,u,0);s[num].other=num-1;
    }
    st1=1+n;ed1=n;
    LL ans=0;
    while (bt()==true)
        ans=ans+find(st1,MAX);
    printf("%lld",ans);
    return 0;
}

顺便,通过这题,我学会了dijkstra,其实和上面那个有堆优化的SPFA差不多,应该还快些,我看了一下,时间复杂度应该是 O(nlogn) ,我也没查过资料QuQ


#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define swap(x,y) {int tt=x;x=y;y=tt;}
using namespace std;
typedef long long LL;
const int N=505*2;
const int M=100005;
const LL MAX=1LL<<60;
struct qq{int x,y,last,other;LL z;}s[M*4];
int num,last[N];
int n,m;
void init (int x,int y,LL z)
{
    num++;
    s[num].x=x;s[num].y=y;s[num].z=z;
    s[num].last=last[x];
    last[x]=num;
}
int X[M],Y[M];
LL Z[M];
LL t[N];
priority_queue < pair <LL,int >,vector<pair<LL,int> >,greater<pair<LL,int> > > q;
bool in[N];
void dijkstra ()
{
    memset(t,127,sizeof(t));
    memset(in,false,sizeof(in));
    q.push(make_pair(0,1));t[1]=0;
    while (!q.empty())
    {
        int x=q.top().second;q.pop();
        if (in[x]==true) continue;
        in[x]=true;
        for (int u=last[x];u!=-1;u=s[u].last)
        {
            int y=s[u].y;
            if (t[y]>t[x]+s[u].z)
            {
                t[y]=t[x]+s[u].z;
                 q.push(make_pair(t[y],y));
            }
        }
    }
    //printf("YES:%lld\n",t[n]);
}
void dfs ()
{
    for (int u=1;u<=m;u++)
    {
        if (t[X[u]]+Z[u]==t[Y[u]])
        {
            init(X[u]+n,Y[u],MAX);s[num].other=num+1;
            init(Y[u],X[u]+n,0);s[num].other=num-1;
        }
        swap(X[u],Y[u]);
        if (t[X[u]]+Z[u]==t[Y[u]])
        {
            init(X[u]+n,Y[u],MAX);s[num].other=num+1;
            init(Y[u],X[u]+n,0);s[num].other=num-1;
        }
    }
    /*if (x==1) return ;
    if (in[x]==true) return ;
    in[x]=true;
    for (int u=1;u<=tt[x][0];u++)
    {
        init(tt[x][u]+n,x,MAX);s[num].other=num+1;
        init(x,tt[x][u]+n,0);s[num].other=num-1;
        dfs(tt[x][u]);
    }*/
}
int h[N];
int st1,ed1;
int Q[N];
bool bt ()
{
    memset(h,0,sizeof(h));
    int st=1,ed=2;
    h[st1]=1;
    Q[st]=st1;
    while (st!=ed)
    {
        int x=Q[st];
        for (int u=last[x];u!=-1;u=s[u].last)
        {
            int y=s[u].y;
            if (s[u].z>0&&h[y]==0)
            {
                h[y]=h[x]+1;
                Q[ed]=y;
                ed++;
            }
        }
        st++;
    }
    if (h[ed1]!=0) return true;
    return false;
}
LL mymin (LL x,LL y)
{
    return x<y?x:y;
}
LL find (int x,LL f)
{
    if (x==ed1) return f;
    LL s1=0,t;
    for (int u=last[x];u!=-1;u=s[u].last)
    {
        int y=s[u].y;
        if (s[u].z>0&&h[y]==(h[x]+1)&&s1<f)
        {
            t=find(y,mymin(s[u].z,f-s1));
            s1+=t;
            s[u].z-=t;
            s[s[u].other].z+=t;
        }
    }
    if (s1==0) h[x]=0;
    return s1;
}
int main()
{
    num=0;memset(last,-1,sizeof(last));
    scanf("%d%d",&n,&m);
    for (int u=1;u<=m;u++)
    {
        int x,y;
        LL z;
        scanf("%d%d%lld",&X[u],&Y[u],&Z[u]);
        init(X[u],Y[u],Z[u]);init(Y[u],X[u],Z[u]);
    }
    dijkstra();
    num=0;memset(last,-1,sizeof(last));
    dfs();
    for (int u=1;u<=n;u++)
    {
        LL a;
        scanf("%lld",&a);
        if (u==1||u==n) continue;
        init(u,u+n,a);s[num].other=num+1;
        init(u+n,u,0);s[num].other=num-1;
    }
    st1=1+n;ed1=n;
    LL ans=0;
    while (bt()==true)
        ans=ans+find(st1,MAX);
    printf("%lld",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值