zoukankan      html  css  js  c++  java
  • HDU4067 Random Maze(最小费用最大流)

    题目大概说,给一张图,删除其中一些单向边,使起点s出度比入度多1,终点t入度比出度多1,其他点出度等于入度。其中删除边的费用是bi,保留边的费用是ai,问完成要求最小的费用是多少。

    一开始我想到和混合图欧拉回路(POJ1637)的类似构造方法:

    • 假设所有边一开始都是保留的,算出各个点的入度和出度,另外s点的出度-1,t点的入度-1;
    • 然后把出度-入度等于正数的点源点向其连一条容量为出度-入度的边,等于负数的点其向汇点连一条容量为入度-出度的边
    • 这样就是要通过删除边使那些与源汇相连的边满流,这样就满足各个点度的要求;而删除一条边<u,v>会使u的出度-1,v的入度-1,这样在容量网络中由u向v连容量1费用bi-ai的边
    • Σai-MCMF就是答案

    不过这样是错的= =而且因为负环死循环TLE了。我试图想拆点消除负环,发现两端点都与源点或汇点相连的边都不起作用,觉得怪怪的好像不大对,提交果然是WA的。

    正确的做法是:一开始不是假设所有边都是保留的,而是贪心地先确定最少的费用,即如果ai<bi则保留否则删除!

    然后接下去的做法也是类似的,我就不赘述了。。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<algorithm>
      5 using namespace std;
      6 #define INF (1<<30)
      7 #define MAXN 111
      8 #define MAXM 8888
      9 struct Edge{
     10     int u,v,cap,cost,next;
     11 }edge[MAXM];
     12 int vs,vt,NV,NE,head[MAXN];
     13 void addEdge(int u,int v,int cap,int cost){
     14     edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
     15     edge[NE].next=head[u]; head[u]=NE++;
     16     edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
     17     edge[NE].next=head[v]; head[v]=NE++;
     18 }
     19 int d[MAXN],pre[MAXN];
     20 bool vis[MAXN];
     21 bool SPFA(){
     22     for(int i=0; i<NV; ++i){
     23         d[i]=INF; vis[i]=0;
     24     }
     25     d[vs]=0; vis[vs]=1;
     26     queue<int> que;
     27     que.push(vs);
     28     while(!que.empty()){
     29         int u=que.front(); que.pop();
     30         for(int i=head[u]; i!=-1; i=edge[i].next){
     31             int v=edge[i].v;
     32             if(edge[i].cap && d[v]>d[u]+edge[i].cost){
     33                 d[v]=d[u]+edge[i].cost;
     34                 pre[v]=i;
     35                 if(!vis[v]){
     36                     vis[v]=1;
     37                     que.push(v);
     38                 }
     39             }
     40         }
     41         vis[u]=0;
     42     }
     43     return d[vt]!=INF;
     44 }
     45 int tot;
     46 int MCMF(){
     47     int res=0,mxflow=0;
     48     while(SPFA()){
     49         int flow=INF,cost=0;
     50         for(int u=vt; u!=vs; u=edge[pre[u]].u){
     51             flow=min(flow,edge[pre[u]].cap);
     52         }
     53         mxflow+=flow;
     54         for(int u=vt; u!=vs; u=edge[pre[u]].u){
     55             edge[pre[u]].cap-=flow;
     56             edge[pre[u]^1].cap+=flow;
     57             cost+=flow*edge[pre[u]].cost;
     58         }
     59         res+=cost;
     60     }
     61     if(tot!=mxflow) return INF;
     62     return res;
     63 }
     64 int u[2222],v[2222],w1[2222],w2[2222];
     65 int deg[MAXN];
     66 int main(){
     67     int T,n,m,s,t;
     68     scanf("%d",&T);
     69     for(int cse=1; cse<=T; ++cse){
     70         scanf("%d%d%d%d",&n,&m,&s,&t);
     71         int res=0;
     72         memset(deg,0,sizeof(deg));
     73         --deg[s]; ++deg[t];
     74         for(int i=0; i<m; ++i){
     75             scanf("%d%d%d%d",u+i,v+i,w1+i,w2+i);
     76             if(w1[i]<w2[i]){
     77                 ++deg[u[i]];
     78                 --deg[v[i]];
     79                 res+=w1[i];
     80             }else{
     81                 res+=w2[i];
     82             }
     83         }
     84         tot=0;
     85         vs=0; vt=n+1; NV=vt+1; NE=0;
     86         memset(head,-1,sizeof(head));
     87         for(int i=1; i<=n; ++i){
     88             if(deg[i]>0) addEdge(vs,i,deg[i],0),tot+=deg[i];
     89             else addEdge(i,vt,-deg[i],0);
     90         }
     91         for(int i=0; i<m; ++i){
     92             if(w1[i]<w2[i]){
     93                 addEdge(u[i],v[i],1,w2[i]-w1[i]);
     94             }else{
     95                 addEdge(v[i],u[i],1,w1[i]-w2[i]);
     96             }
     97         }
     98         int tmp=MCMF();
     99         if(tmp==INF) printf("Case %d: impossible
    ",cse);
    100         else printf("Case %d: %d
    ",cse,res+tmp);
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    面向对象程序设计第五次作业(修改)
    C++作业 一
    面向对象程序设计第四次作业
    面向对象程序设计第三次作业
    C++学习笔记3
    C++学习笔记2
    C++学习笔记1
    面向对象程序设计作业二
    面向对象程序设计第二次作业
    随笔
  • 原文地址:https://www.cnblogs.com/WABoss/p/5395566.html
Copyright © 2011-2022 走看看