P2153 [SDOI2009]晨跑

来源:互联网 发布:mac系统视频剪辑软件 编辑:程序博客网 时间:2024/05/29 10:07

这里写图片描述

题目要求不能通过相同的点,限制点,和蜥蜴那个题类似,将每个点拆成两个点,中间连一条边,因为每个点只能通过一次,所以边的流量为1
因为起点和汇点不算十字路口,所以不用拆,在与1号点直接相连的点和1号点之间连一条流量为1的边,与n号点相连的点一样如此处理,然后用最小费用最大流就可以了。最大流即为天数,最小费用即为总路程。
需要注意的问题是构建cost的反向边。

代码

#include<iostream>#include<cstring>#include<string>#include<cstdio>#include<algorithm>#include<queue>#include<vector>#define INF 2139062143using namespace std;int n,m;int pre[409],f[409];int cost[409][409],cap[409][409];int mflow=0,mcost=0;int flow[409],dis[409];int bfs(int s,int t){    queue <int> q;    while(!q.empty()) q.pop();    memset(pre,-1,sizeof(pre));    memset(dis,127,sizeof(dis));    memset(f,0,sizeof(f));    q.push(s);    pre[s]=0;    flow[s]=INF;    dis[s]=0;    f[s]=1;    while(!q.empty())    {        int k=q.front();        q.pop();        f[k]=0;        for(int i=1;i<2*n;i++)        {            if(cap[k][i]>0&&dis[i]>dis[k]+cost[k][i])            {                dis[i]=dis[k]+cost[k][i];                flow[i]=min(flow[k],cap[k][i]);                pre[i]=k;                if(!f[i]) q.push(i),f[i]=1;            }        }    }    if(pre[t]==-1) return -1;    return flow[t]; }void maxflow(int s,int t){    int d;    while(1)    {        d=bfs(s,t);        if(d==-1) return;        int k=t;        while(k!=s)        {            cap[pre[k]][k]-=d;            cap[k][pre[k]]+=d;            k=pre[k];        }        mflow+=d;        mcost+=d*dis[t];    }    return;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        int cu;        if(a==1) cu=1;        else cu=a+n;         cap[cu][b]=1;        cost[cu][b]=c;        cost[b][cu]=-c;//反向边    }    for(int i=2;i<=n-1;i++)      cap[i][i+n]=1;    maxflow(1,n);    printf("%d %d",mflow,mcost);    return 0;} 
1 0
原创粉丝点击