湖南第十届省赛 Double Shortest Paths

费用流模版题
开始想用两次广搜,后来发现有细节很难处理,后来才知道是费用流。

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int sumFlow;
const int MAXN = 505;
const int MAXM = 10005;
const int inf = 0x3f3f3f3f;
struct Edge
{
    int u;
    int v;
    int cap;
    int cost;
    int next;
}edge[MAXM<<2];
int NE;
int head[MAXN], dist[MAXN], pp[MAXN];
bool vis[MAXN];
void init(){
    NE=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost){
    edge[NE].u=u;edge[NE].v=v;edge[NE].cap=cap;edge[NE].cost=cost;
    edge[NE].next=head[u];head[u]=NE++;
    edge[NE].u=v;edge[NE].v=u;edge[NE].cap=0;edge[NE].cost=-cost;
    edge[NE].next=head[v];head[v]=NE++;
}
bool SPFA(int s,int t,int n)
{
    int i,u,v;
    queue<int>qu;
    memset(vis,false,sizeof(vis));
    memset(pp,-1,sizeof(pp));
    for(i=0;i<=n;i++)
        dist[i]=inf;
    vis[s]=true;
    dist[s]=0;
    qu.push(s);
    while(!qu.empty())
    {
        u=qu.front();
        qu.pop();
        vis[u]=false;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(edge[i].cap&&dist[v]>dist[u]+edge[i].cost)
            {
                dist[v]=dist[u]+edge[i].cost;
                pp[v]=i;
                if(!vis[v])
                {
                    qu.push(v);
                    vis[v]=true;
                }
            }
        }
    }
    if(dist[t]==inf)
        return false;
    return true;
}
int MCMF(int s,int t,int n)
{
    int flow=0; /// 总流量
    int i,minflow,mincost;
    mincost=0;
    while(SPFA(s,t,n))
    {
        minflow=inf+1;
        for(i=pp[t];i!=-1;i=pp[edge[i].u])
            if(edge[i].cap<minflow)
                minflow=edge[i].cap;
        flow+=minflow;
        for(i=pp[t];i!=-1;i=pp[edge[i].u])
        {
            edge[i].cap-=minflow;
            edge[i^1].cap+=minflow;
        }
        mincost+=dist[t]*minflow;
    }
    sumFlow=flow; /// 最大流
    return mincost;
}

int main()
{
    //freopen("d.in","r",stdin);
// freopen("D_out.txt","w",stdout);
    int n,m;
    int u,v,c,k;
    int coun=0;
    while(~scanf("%d%d",&n,&m)){
        printf("Case %d: ",++coun);
        init();
        int S=0;
        int T=n+1;
        while(m--){
            scanf("%d%d%d%d",&u,&v,&c,&k);
            addedge(u,v,1,c);
            addedge(u,v,1,c+k);
        }
        addedge(S,1,2,0);
        addedge(n,T,2,0);
        int ans=MCMF(S,T,T+1);
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(湖南第十届省赛 Double Shortest Paths)