3931: [CQOI2015]网络吞吐量 最短路+最大流

。。题意说的很清楚了,先求最短路径图再拆点网络流。
居然没被long long坑,1A赞。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define inf 1e18
#define ll long long 
#define pa pair<ll,int>
using namespace std;
int n,m,cnt,T;
int v[100005],u[100005],w[100005];
int next[500005],list[500005];
int head[1005], cur[1005],q[1005];
ll dis[1005],key[500005];
bool vis[1005];
priority_queue<pa,vector<pa>,greater<pa> > heap;
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline void insert(int x,int y,ll z)
{
    next[++cnt]=head[x];
    head[x]=cnt;
    list[cnt]=y;
    key[cnt]=z;
}
inline void dijkstra()
{
    for (int i=1;i<=n;i++) dis[i]=inf;
    dis[1]=0;
    heap.push(make_pair(0,1));
    while (!heap.empty())
    {
        int x=heap.top().second; heap.pop();
        if (vis[x]) continue; vis[x]=1;
        for (int i=head[x];i;i=next[i])
            if (dis[list[i]]>dis[x]+key[i])
            {
                dis[list[i]]=dis[x]+key[i];
                heap.push(make_pair(dis[list[i]],list[i]));
            }
    }
}
inline bool BFS()
{
    for (int i=1;i<=T;i++) dis[i]=-1;
    dis[1]=1; q[1]=1;
    int t=0,w=1,x;
    while (t<w)
    {
        x=q[++t];
        for (int i=head[x];i;i=next[i])
            if (key[i]&&dis[list[i]]==-1)
                dis[list[i]]=dis[x]+1,q[++w]=list[i];
    }
    return dis[T]!=-1;
}
ll find(int x,ll flow)
{
    if (x==T) return flow;
    ll w,used=0;
    for (int i=cur[x];i;i=next[i])
        if (key[i]&&dis[list[i]]==dis[x]+1)
        {
            w=find(list[i],min(key[i],flow-used));
            key[i]-=w; key[i^1]+=w; used+=w;
            if (used==flow) return used;
        }
    if (!used) dis[x]=-1;
    return used;
}
inline ll dinic()
{
    ll tmp=0;
    while (BFS())
    {
        for (int i=1;i<=T;i++) cur[i]=head[i];
        tmp+=find(1,inf);
    }
    return tmp;
}
int main()
{
    n=read(); m=read();
    for (int i=1;i<=m;i++)
    {
        u[i]=read(),v[i]=read(),w[i]=read();
        insert(u[i],v[i],w[i]); insert(v[i],u[i],w[i]);
    }
    dijkstra();
    cnt=1; T=2*n;
    memset(head,0,sizeof(head));
    for (int i=1;i<=m;i++)
    {
        if (dis[u[i]]+w[i]==dis[v[i]]) 
            insert(u[i]+n,v[i],inf),insert(v[i],u[i]+n,0);
        if (dis[v[i]]+w[i]==dis[u[i]])
            insert(v[i]+n,u[i],inf),insert(u[i],v[i]+n,0);
    }
    for (int i=1;i<=n;i++)
    {
        int c=read();
        if (i==1||i==n) insert(i,i+n,inf),insert(i+n,i,0);
        else insert(i,i+n,c),insert(i+n,i,0);
    }
    cout << dinic() << endl;
    return 0;
}   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值