HDU 4411

来源:互联网 发布:淘宝改标题影响权重 编辑:程序博客网 时间:2024/06/05 15:15

费用流

建图见下面代码,

解释下这条加边addedge(2*v+1,2*v+2,k,0);

费用流第一遍跑肯定是跑含有v条负无穷的边。

如果以后跑反向边是对第一次跑n条负无穷的边的优化,如果没有优化就干脆不出动警力

#include<cstdio>#include<cstring>#include<queue>#define N 300#define inf -100000000using namespace std;typedef long long ll;int n,cnt;int head[N],pre[N],vis[N];ll dis[N];int map[110][110];ll ans;struct Edge{    int u,v,c,next;    ll w;}edge[40010];void init(){    memset(head,-1,sizeof(head));    memset(map,-1,sizeof(map));    for(int i=0;i<n/2;i++)        map[i][i]=0;    cnt=0;}void addedge(int u,int v,int cap,int cost){    edge[cnt].u=u;    edge[cnt].v=v;    edge[cnt].c=cap;    edge[cnt].w=cost;    edge[cnt].next=head[u];    head[u]=cnt++;    edge[cnt].u=v;    edge[cnt].v=u;    edge[cnt].c=0;    edge[cnt].w=-cost;    edge[cnt].next=head[v];    head[v]=cnt++;}bool spfa(){    int i,j;    queue<int>q;    q.push(0);    for(i=1;i<=n;i++){        dis[i]=-inf;        vis[i]=0;    }    dis[0]=0,vis[0]=1;    while(!q.empty()){        int u=q.front();        q.pop();        vis[u]=0;        for(i=head[u];i!=-1;i=edge[i].next){            int v=edge[i].v;            if(edge[i].c && dis[v] > dis[u]+edge[i].w){                dis[v]=dis[u]+edge[i].w;                pre[v]=i;                if(!vis[v]){                    vis[v]=1;                    q.push(v);                }            }        }    }    if(dis[n]==-inf)return 0;    return 1;}void end(){    int u,p,cap=-1;    for(u=n;u;u=edge[p].u){        p=pre[u];        if(cap==-1 || cap>edge[p].c)            cap=edge[p].c;    }    for(u=n;u;u=edge[p].u){        p=pre[u];        edge[p].c-=cap;        edge[p^1].c+=cap;        ans+=cap*edge[p].w;    }}int main(){    int v,e,k,i,j,p;    int u,vv,w;    while(scanf("%d %d %d",&v,&e,&k)){        if(v==0 && e==0 && k==0)break;        n=2*v+2;        init();        for(i=1;i<=e;i++){            scanf("%d %d %d",&u,&vv,&w);            if(map[u][vv]==-1 || map[u][vv]>w)                map[u][vv]=map[vv][u]=w;        }        for(p=0;p<=v;p++)            for(i=0;i<=v;i++){                if(map[i][p]==-1)continue;                for(j=0;j<=v;j++){                    if(map[p][j]==-1)continue;                    if(map[i][j]==-1 || map[i][j]>map[i][p]+map[p][j])                        map[j][i]=map[i][j]=map[i][p]+map[p][j];                }            }        addedge(0,2*v+1,k,0);        addedge(2*v+1,2*v+2,k,0);        for(i=1;i<=v;i++){            addedge(2*v+1,i*2-1,-inf,map[0][i]);            addedge(i*2,n,-inf,map[i][0]);            addedge(2*i-1,2*i,1,inf);            for(j=i+1;j<=v;j++)                addedge(i*2,j*2-1,-inf,map[i][j]);        }        ans=0;        while(spfa())            end();        printf("%lld\n",ans-v*inf);    }    return 0;}



原创粉丝点击