• 专题十一 网络流


    专题链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68128#overview

    网络流基础知识:http://www.cnblogs.com/yaoyueduzhen/p/5020722.html

    本专题考察网络流问题, 包含最大流和最小费用最大流,请使用高效模板。

    A.  poj3436    ACM Computer Factory

    分析:这个是一个网络流,对流过每个点的流量有限制,这样就需要拆点,把每个结点拆成两个,一个入点,一个出点,并从入点到出点连接一条边流量为点的的流向限制,把所有接入该点的边接入它的入点,从该点流出的边从出点流出。

    建图方法,每个机器是一个点,把源与所有没有必须元件的点连接,所有完整元件的点与汇连接,若一台机器的输出能符合另一台机器的输入条件则连一条边。把每个机器拆点,其内部边流量为其生产速度。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int MAXN=120;
      8 const int MAXM=120*120;
      9 const int INF=0x3f3f3f3f;
     10 int p,n;
     11 int q[MAXN];
     12 int in[MAXN][MAXN],out[MAXN][MAXN];
     13 
     14 struct Edge 
     15 {
     16     int to, next, cap, flow;
     17 }edge[MAXM];
     18 int tol;
     19 int head[MAXN];
     20 void init() 
     21 {
     22     tol = 2;
     23     memset(head, -1, sizeof(head));
     24 }
     25 void addedge(int u, int v, int w, int rw=0) 
     26 {
     27     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     28     edge[tol].next = head[u]; head[u] = tol++;
     29     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     30     edge[tol].next = head[v]; head[v] = tol++;
     31 }
     32 int Q[MAXN];
     33 int dep[MAXN], cur[MAXN], sta[MAXN];
     34 bool bfs(int s, int t, int n) 
     35 {
     36     int front = 0, tail = 0;
     37     memset(dep, -1, sizeof(dep));
     38     dep[s] = 0;
     39     Q[tail++] = s;
     40     while(front < tail)
     41     {
     42         int u = Q[front++];
     43         for(int i = head[u]; i != -1; i = edge[i].next) 
     44         {
     45             int v = edge[i].to;
     46             if(edge[i].cap > edge[i].flow && dep[v] == -1)                 
     47             {
     48                 dep[v] = dep[u] + 1;
     49                 if(v == t) return true;
     50                 Q[tail++] = v;
     51             }
     52         }
     53     }
     54     return false;
     55 }
     56 
     57 int dinic(int s, int t, int n) 
     58 {
     59     int maxflow = 0;
     60     while(bfs(s, t, n)) 
     61     {
     62         for(int i = 0; i < n; i++) cur[i] = head[i];
     63         int u = s, tail = 0;
     64         while(cur[s] != -1)
     65         {
     66             if(u == t) 
     67             {
     68                 int tp = INF;
     69                 for(int i = tail-1; i >= 0; i--)
     70                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     71                 maxflow+=tp;
     72                 for(int i = tail-1; i >= 0; i--) 
     73                 {
     74                     edge[sta[i]].flow+=tp;
     75                     edge[sta[i]^1].flow-=tp;
     76                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     77                         tail = i;
     78                 }
     79                 u = edge[sta[tail]^1].to;
     80             }
     81             else 
     82                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     83                 {
     84                     sta[tail++] = cur[u];
     85                     u = edge[cur[u]].to;
     86                 }
     87                 else 
     88                 {
     89                     while(u != s && cur[u] == -1)
     90                         u = edge[sta[--tail]^1].to;
     91                     cur[u] = edge[cur[u]].next;
     92                 }
     93         }
     94     }
     95     return maxflow;
     96 }
     97 
     98 int main()
     99 {
    100     scanf("%d%d",&p,&n);
    101     init();
    102     for(int i=1;i<=n;++i)
    103     {
    104         scanf("%d",&q[i]);
    105         for(int j=1;j<=p;++j)
    106             scanf("%d",&in[i][j]);
    107         for(int j=1;j<=p;++j)
    108             scanf("%d",&out[i][j]);
    109     }
    110     for(int i=1;i<=n;++i)
    111         addedge(i,n+i,q[i]);
    112     for(int i=1;i<=n;++i)
    113         for(int j=1;j<=n;++j)
    114             if(i!=j)
    115             {
    116                 bool flag=true;
    117                 for(int k=1;k<=p;++k)
    118                 {
    119                     if(out[i][k]==0&&in[j][k]==1)
    120                     {
    121                         flag=false;
    122                         break;
    123                     }
    124                     if(out[i][k]==1&&in[j][k]==0)
    125                     {
    126                         flag=false;
    127                         break;
    128                     }
    129                 }
    130                 if(flag)
    131                     addedge(i+n,j,min(q[i],q[j]));
    132             }
    133     for(int i=1;i<=n;++i)
    134     {
    135         bool f=true;
    136         for(int j=1;j<=p;++j)
    137         {
    138             if(in[i][j]==1)
    139             {
    140                 f=false;
    141                 break;
    142             }
    143         }
    144         if(f)    addedge(0,i,q[i]);
    145     }
    146     for(int i=1;i<=n;++i)
    147     {
    148         bool f=true;
    149         for(int j=1;j<=p;++j)
    150         {
    151             if(out[i][j]==0)
    152             {
    153                 f=false;
    154                 break;
    155             }
    156         }
    157         if(f) 
    158             addedge(i+n,2*n+1,q[i]);
    159     }
    160     int res=dinic(0,2*n+1,2*n+2);
    161     int count=0;
    162     for(int i=1;i<=n;++i)
    163         for(int j=head[i+n];j!=-1;j=edge[j].next)
    164             if(edge[j].to!=2*n+1&&edge[j].flow>0)
    165                 count++;
    166     cout<<res<<" "<<count<<endl;
    167     for(int i=1;i<=n;++i)
    168         for(int j=head[i+n];j!=-1;j=edge[j].next)
    169             if(edge[j].to!=2*n+1&&edge[j].flow>0)
    170                 cout<<i<<" "<<edge[j].to<<" "<<edge[j].flow<<endl;
    171     return 0;
    172 }
    View Code

    B.  poj3281     Dining

    建图方法:为使每一头牛都对应每一份食物与饮料,需要将每头牛拆点,一共有2*n+f+d+2个顶点,0表示源点,2*n+f+d+1表示汇点,由源点指向食物,再由食物指向牛,牛指向自己的对应点,再指向对应的饮料,饮料再指向汇点。全部是有向的边,而且权值全部为1,1到f为食物点,f+1到f+2*n为牛点,f+2*n+1到f+2*n+d为饮料点。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int MAXN = 500;
      8 const int MAXM = 500*500;
      9 const int INF = 0x3f3f3f3f;
     10 struct Edge 
     11 {
     12     int to, next, cap, flow;
     13 }edge[MAXM];
     14 int tol;
     15 int head[MAXN];
     16 int gap[MAXN], dep[MAXN], cur[MAXN];
     17 void init() 
     18 {
     19     tol = 0;
     20     memset(head, -1, sizeof(head));
     21 }
     22 void addedge(int u, int v, int w, int rw = 0) 
     23 {
     24     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     25     edge[tol].next = head[u]; head[u] = tol++;
     26     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     27     edge[tol].next = head[v]; head[v] = tol++;
     28 }
     29 int Q[MAXN];
     30 void BFS(int start, int end) 
     31 {
     32     memset(dep, -1, sizeof(dep));
     33     memset(gap, 0, sizeof(gap));
     34     gap[0] = 1;
     35     int front = 0, rear = 0;
     36     dep[end] = 0;
     37     Q[rear++] = end;
     38     while(front != end) {
     39         int u = Q[front++];
     40         for(int i = head[u]; i != -1; i = edge[i].next) {
     41             int v = edge[i].to;
     42             if(dep[v] != -1) continue;
     43             Q[rear++] = v;
     44             dep[v] = dep[u] + 1;
     45             gap[dep[v]]++;
     46         }
     47     }
     48 }
     49 int S[MAXN];
     50 int sap(int start, int end, int N) {
     51     BFS(start, end);
     52     memcpy(cur, head, sizeof(head));
     53     int top = 0;
     54     int u = start;
     55     int ans = 0;
     56     while(dep[start] < N) 
     57     {
     58         if(u == end) 
     59         {
     60             int Min = INF;
     61             int inser;
     62             for(int i = 0; i < top; i++)
     63                 if(Min > edge[S[i]].cap - edge[S[i]].flow) {
     64                     Min = edge[S[i]].cap - edge[S[i]].flow;
     65                     inser = i;
     66                 }
     67             for(int i = 0; i < top; i++) 
     68             {
     69                 edge[S[i]].flow += Min;
     70                 edge[S[i]^1].flow -= Min;
     71             }
     72             ans += Min;
     73             top = inser;
     74             u = edge[S[top]^1].to;
     75             continue;
     76         }
     77         bool flag = false;
     78         int v;
     79         for(int i = cur[u]; i != -1; i = edge[i].next) 
     80         {
     81             v = edge[i].to;
     82             if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u])                 {
     83                 flag = true;
     84                 cur[u] = i;
     85                 break;
     86             }
     87         }
     88         if(flag) 
     89         {
     90             S[top++] = cur[u];
     91             u = v;
     92             continue;
     93         }
     94         int Min = N;
     95         for(int i = head[u]; i != -1; i = edge[i].next)
     96             if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) 
     97             {
     98                 Min = dep[edge[i].to];
     99                 cur[u] = i;
    100             }
    101         gap[dep[u]]--;
    102         if(!gap[dep[u]]) return ans;
    103         dep[u] = Min + 1;
    104         gap[dep[u]]++;
    105         if(u != start) u = edge[S[--top]^1].to;
    106     }
    107     return ans;
    108 }
    109 
    110 int f,n,d;
    111 int main()
    112 {
    113     scanf("%d%d%d",&n,&f,&d);
    114     init();
    115     for(int i=1;i<=n;++i)
    116     {
    117         int a,b,num;
    118         scanf("%d%d",&a,&b);
    119         for(int j=1;j<=a;++j)
    120         {
    121             scanf("%d",&num);
    122             addedge(num,i+f,1);
    123         }
    124         for(int j=1;j<=b;++j)
    125         {
    126             scanf("%d",&num);
    127             addedge(i+f+n,f+2*n+num,1);
    128         }
    129         addedge(f+i,f+n+i,1);
    130     }
    131     for(int i=1;i<=f;++i)
    132         addedge(0,i,1);
    133     for(int i=1;i<=d;++i)
    134         addedge(f+2*n+i,f+2*n+d+1,1);
    135     int res=sap(0,f+2*n+d+1,f+2*n+d+2);
    136     cout<<res<<endl;
    137     return 0;
    138 }
    View Code

    C.   poj1087    A Plug for UNIX

    题目大意:这题题目意思实在太难懂,不过题目意思搞清楚之后还是比较好做的。

    题目中有三种物品:插座,电器和转换器。

    首先有n种插座,n种插座用字符串表示,这n种插座可以理解为是插在电源上的插座。
    然后有m个电器,现在电器要充电,电器用字符串表示,每个电器都有自己需要插的插座
    (这个插座可以不是那n个插在电源上的插座,可以是其他的插座)。
    最后有k种转换器:s1 s2代表这个转换器可以将s1插座转换成s2插座,这些s1与s2也可以不是那n个插在电源上的插座。

    给出这些个信息问你还有多少个电器没有插座可以用。

    建图方法:
    建一个源点,指向所有电器,容量为1。所有电器指向他们可以插的那个插头上,容量为1。
    如果一个插头可以转换另一个插头,那么将s1指向s2,容量为无限大,将所有插在电源上的插头指向汇点,容量为1。

    最后求源点到汇点的最大流即可,不过建图会比较复杂,因为涉及到字符串的处理,所以用map容器存储结点编号比较好做点。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<queue>
      6 #include<map>
      7 #include<string>
      8 
      9 using namespace std;
     10 const int MAXN = 1010;
     11 const int MAXM = 1000020;
     12 const int INF = 0x3f3f3f3f;
     13 struct Edge 
     14 {
     15     int to, next, cap, flow;
     16 }edge[MAXM];
     17 int tol;
     18 int head[MAXN];
     19 void init() 
     20 {
     21     tol = 2;
     22     memset(head, -1, sizeof(head));
     23 }
     24 void addedge(int u, int v, int w, int rw=0) 
     25 {
     26     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     27     edge[tol].next = head[u]; head[u] = tol++;
     28     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     29     edge[tol].next = head[v]; head[v] = tol++;
     30 }
     31 int Q[MAXN];
     32 int dep[MAXN], cur[MAXN], sta[MAXN];
     33 bool bfs(int s, int t, int n) 
     34 {
     35     int front = 0, tail = 0;
     36     memset(dep, -1, sizeof(dep[0])*(n+1));
     37     dep[s] = 0;
     38     Q[tail++] = s;
     39     while(front < tail)
     40     {
     41         int u = Q[front++];
     42         for(int i = head[u]; i != -1; i = edge[i].next) 
     43         {
     44             int v = edge[i].to;
     45             if(edge[i].cap > edge[i].flow && dep[v] == -1)                 {
     46                 dep[v] = dep[u] + 1;
     47                 if(v == t) return true;
     48                 Q[tail++] = v;
     49             }
     50         }
     51     }
     52     return false;
     53 }
     54 int dinic(int s, int t, int n) {
     55     int maxflow = 0;
     56     while(bfs(s, t, n)) {
     57         for(int i = 0; i < n; i++) cur[i] = head[i];
     58         int u = s, tail = 0;
     59         while(cur[s] != -1)
     60         {
     61             if(u == t) 
     62             {
     63                 int tp = INF;
     64                 for(int i = tail-1; i >= 0; i--)
     65                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     66                 maxflow+=tp;
     67                 for(int i = tail-1; i >= 0; i--) {
     68                     edge[sta[i]].flow+=tp;
     69                     edge[sta[i]^1].flow-=tp;
     70                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     71                         tail = i;
     72                 }
     73                 u = edge[sta[tail]^1].to;
     74             }
     75             else 
     76                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     77                 {
     78                     sta[tail++] = cur[u];
     79                     u = edge[cur[u]].to;
     80                 }
     81                 else 
     82                 {
     83                     while(u != s && cur[u] == -1)
     84                         u = edge[sta[--tail]^1].to;
     85                     cur[u] = edge[cur[u]].next;
     86                 }
     87         }
     88     }
     89     return maxflow;
     90 }
     91 
     92 map<string,int> m1,m2;
     93 int n,m,k;
     94 
     95 int main()
     96 {
     97     m1.clear();
     98     m2.clear();
     99     init();
    100     scanf("%d",&n);
    101     for(int i=1;i<=n;++i)
    102     {
    103         string s;
    104         cin>>s;
    105         m1[s]=i;
    106         addedge(0,i,1);
    107     }
    108     scanf("%d",&m);
    109     int cnt=n;
    110     for(int i=1;i<=m;++i)
    111     {
    112         string s1,s2;
    113         cin>>s1>>s2;
    114         m2[s1]=i+300;
    115         if(m1[s2]==0)
    116             m1[s2]=++cnt;
    117         addedge(m1[s2],m2[s1],1);
    118         addedge(m2[s1],400,1);
    119     }
    120     scanf("%d",&k);
    121     string a1[MAXN],a2[MAXN];
    122     for(int i=1;i<=k;++i)
    123         cin>>a1[i]>>a2[i];
    124     for(int i=1;i<=k;++i)
    125     {
    126         if(m1[a1[i]]==0)
    127             m1[a1[i]]=++cnt;
    128         if(m1[a2[i]]==0)
    129             m1[a2[i]]=++cnt;
    130         addedge(m1[a2[i]],m1[a1[i]],INF);
    131     }
    132     int res=dinic(0,400,401);
    133 //    cout<<m<<"   "<<res<<endl;
    134     cout<<m-res<<endl;
    135     return 0;
    136 }
    View Code

     D.   poj2195      Going Home

    题意:有若干个人和若干个房子在一个给定网格中,每人走一个都要一定花费,每个房子只能容纳一人,现要求让所有人进入房子,且总花费最小。
    分析:简单题,题目中关键字为:每房子容纳一人,行走有花费,典型的最小费用最大流问题。建图加入超级终点和源点,注意对所有房子和人之间建立边。最后求最小费用最大流即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<queue>
      6 
      7 using namespace std;
      8 const int MAXN = 10000;
      9 const int MAXM = 100000;
     10 const int INF = 0x3f3f3f3f;
     11 struct Edge 
     12 {
     13     int to, next, cap, flow, cost;
     14 }edge[MAXM];
     15 int head[MAXN], tol;
     16 int pre[MAXN], dis[MAXN];
     17 bool vis[MAXN];
     18 int N;
     19 void init(int n) 
     20 {
     21     N = n;
     22     tol = 0;
     23     memset(head, -1, sizeof(head));
     24 }
     25 void addedge(int u, int v, int cap, int cost) 
     26 {
     27     edge[tol].to = v; edge[tol].cap = cap;
     28     edge[tol].cost = cost; edge[tol].flow = 0;
     29     edge[tol].next = head[u]; head[u] = tol++;
     30     edge[tol].to = u; edge[tol].cap = 0;
     31     edge[tol].cost = -cost; edge[tol].flow = 0;
     32     edge[tol].next = head[v]; head[v] = tol++;
     33 }
     34 bool spfa(int s, int t) 
     35 {
     36     queue<int> q;
     37     for(int i = 0; i < N; i++) 
     38     {
     39         dis[i] = INF;
     40         vis[i] = false;
     41         pre[i] = -1;
     42     }
     43     dis[s] = 0; vis[s] = true;
     44     q.push(s);
     45     while(!q.empty()) 
     46     {
     47         int u = q.front();
     48         q.pop();
     49         vis[u] = false;
     50         for(int i = head[u]; i != -1; i = edge[i].next)
     51         { 
     52             int v = edge[i].to;
     53             if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost) 
     54             {
     55                 dis[v] = dis[u] + edge[i].cost;
     56                 pre[v] = i;
     57                 if(!vis[v]) 
     58                 {
     59                     vis[v] = true;
     60                     q.push(v);
     61                 }
     62             }
     63         }
     64     }
     65     if(pre[t] == -1) return false;
     66     else return true;
     67 }
     68 
     69 int minCostMaxflow(int s, int t, int &cost) 
     70 {
     71     int flow = 0;
     72     cost = 0;
     73     while(spfa(s, t))
     74     {
     75         int Min = INF;
     76         for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) 
     77         {
     78             if(Min > edge[i].cap - edge[i].flow)
     79                 Min = edge[i].cap - edge[i].flow;
     80         }
     81         for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) 
     82         {
     83             edge[i].flow += Min;
     84             edge[i^1].flow -= Min;
     85             cost += edge[i].cost * Min;
     86         }
     87         flow += Min;
     88     }
     89     return flow;
     90 }
     91 
     92 int n,m;
     93 char map[MAXN][MAXN];
     94 struct House
     95 {
     96     int x,y;
     97 }house[MAXN];
     98 
     99 struct Man
    100 {
    101     int x,y;
    102 }man[MAXN];
    103 
    104 int dist(int i,int j)
    105 {
    106     return abs(man[i].x-house[j].x)+abs(man[i].y-house[j].y);
    107 }
    108 
    109 int main()
    110 {
    111     while(~scanf("%d%d",&n,&m)&&(n||m))
    112     {
    113         for(int i=0;i<n;++i)
    114             scanf("%s",map[i]);
    115         int mnum=0,hnum=0;
    116         int count=0;
    117         for(int i=0;i<n;++i)
    118             for(int j=0;j<m;++j)
    119             {
    120                 if(map[i][j]=='m')
    121                 {
    122                     count++;
    123                     mnum++;
    124                     man[mnum].x=i+1;
    125                     man[mnum].y=j+1;
    126                 }
    127                 if(map[i][j]=='H')
    128                 {
    129                     hnum++;
    130                     house[hnum].x=i+1;
    131                     house[hnum].y=j+1;
    132                 }
    133             }
    134         init(2*count+2);
    135     //    cout<<count<<endl;
    136         for(int i=1;i<=count;++i)
    137             for(int j=1;j<=count;++j)
    138                 addedge(i,j+count,1,dist(i,j));
    139         for(int i=1;i<=count;++i)
    140         {
    141             addedge(0,i,1,0);
    142             addedge(i+count,2*count+1,1,0);
    143         }
    144         int cost;
    145         minCostMaxflow(0,2*count+1,cost);
    146         cout<<cost<<endl;
    147     }
    148     return 0;
    149 }
    View Code

    E.    poj2516     Minimum Cost

    分析:由于每种物品之间是独立的,所以可以将k种物品分开求最小费用再相加,即对每一种物品建一幅图。可以在建图前先判断是否需求全部能满足。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<queue>
      6 
      7 using namespace std;
      8 const int MAXN = 200;
      9 const int MAXM = 40000;
     10 const int INF = 0x3f3f3f3f;
     11 struct Edge 
     12 {
     13     int to, next, cap, flow, cost;
     14 }edge[MAXM];
     15 int head[MAXN], tol;
     16 int pre[MAXN], dis[MAXN];
     17 bool vis[MAXN];
     18 int N;
     19 void init(int n) 
     20 {
     21     N = n;
     22     tol = 0;
     23     memset(head, -1, sizeof(head));
     24 }
     25 void addedge(int u, int v, int cap, int cost) 
     26 {
     27     edge[tol].to = v; edge[tol].cap = cap;
     28     edge[tol].cost = cost; edge[tol].flow = 0;
     29     edge[tol].next = head[u]; head[u] = tol++;
     30     edge[tol].to = u; edge[tol].cap = 0;
     31     edge[tol].cost = -cost; edge[tol].flow = 0;
     32     edge[tol].next = head[v]; head[v] = tol++;
     33 }
     34 bool spfa(int s, int t) 
     35 {
     36     queue<int> q;
     37     for(int i = 0; i < N; i++) 
     38     {
     39         dis[i] = INF;
     40         vis[i] = false;
     41         pre[i] = -1;
     42     }
     43     dis[s] = 0; vis[s] = true;
     44     q.push(s);
     45     while(!q.empty()) 
     46     {
     47         int u = q.front();
     48         q.pop();
     49         vis[u] = false;
     50         for(int i = head[u]; i != -1; i = edge[i].next)
     51         { 
     52             int v = edge[i].to;
     53             if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost) 
     54             {
     55                 dis[v] = dis[u] + edge[i].cost;
     56                 pre[v] = i;
     57                 if(!vis[v]) 
     58                 {
     59                     vis[v] = true;
     60                     q.push(v);
     61                 }
     62             }
     63         }
     64     }
     65     if(pre[t] == -1) return false;
     66     else return true;
     67 }
     68 
     69 int minCostMaxflow(int s, int t, int &cost) 
     70 {
     71     int flow = 0;
     72     cost = 0;
     73     while(spfa(s, t))
     74     {
     75         int Min = INF;
     76         for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) 
     77         {
     78             if(Min > edge[i].cap - edge[i].flow)
     79                 Min = edge[i].cap - edge[i].flow;
     80         }
     81         for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) 
     82         {
     83             edge[i].flow += Min;
     84             edge[i^1].flow -= Min;
     85             cost += edge[i].cost * Min;
     86         }
     87         flow += Min;
     88     }
     89     return flow;
     90 }
     91 
     92 int n,m,k;
     93 int need[60][60],supply[60][60],cost[60][60],sumneed[60],sumsupply[60];
     94 int main()
     95 {
     96     while(scanf("%d%d%d",&n,&m,&k))
     97     {
     98         if(n==0 && m==0 && k==0)
     99             break;
    100         memset(sumneed,0,sizeof(sumneed));
    101         memset(sumsupply,0,sizeof(sumsupply));
    102         for(int i=1;i<=n;++i)
    103             for(int j=1;j<=k;++j)
    104             {
    105                 scanf("%d",&need[i][j]);
    106                 sumneed[j]+=need[i][j];
    107             }
    108         for(int i=1;i<=m;++i)
    109             for(int j=1;j<=k;++j)
    110             {
    111                 scanf("%d",&supply[i][j]);
    112                 sumsupply[j]+=supply[i][j];
    113             }
    114         bool flag=true;
    115         for(int i=1;i<=k;++i)
    116         {
    117             if(sumsupply[i]<sumneed[i])
    118             {
    119                 flag=false;
    120                 break;
    121             }
    122         }
    123         int res=0;
    124         for(int l=1;l<=k;++l)
    125         {
    126             init(m+n+2);
    127             for(int i=1;i<=n;++i)
    128                 for(int j=1;j<=m;++j)
    129                     scanf("%d",&cost[i][j]);
    130             for(int i=1;i<=m;++i)
    131                 for(int j=1;j<=n;++j)
    132                     addedge(i,j+m,need[j][l],cost[j][i]);
    133             for(int i=1;i<=m;++i)
    134                 addedge(0,i,supply[i][l],0);
    135             for(int i=1;i<=n;++i)
    136                 addedge(i+m,m+n+1,need[i][l],0);
    137             int ans;
    138             minCostMaxflow(0,m+n+1,ans);
    139             res+=ans;
    140         }
    141         if(!flag)
    142             cout<<-1<<endl;
    143         else
    144             cout<<res<<endl;
    145     }
    146     return 0;
    147 }
    View Code

    F.    poj1459     Power Network

    分析:题意比较烦,整理清楚就知道是裸的最大流,需要增加一个超级源点和超级汇点,把所给的发电站都和超级源点相连,把所给的消耗站都和超级汇点相连,最后跑一遍最大流即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<queue>
      6 
      7 using namespace std;
      8 const int MAXN = 1200;
      9 const int MAXM = 120*1200;
     10 const int INF = 0x3f3f3f3f;
     11 struct Edge 
     12 {
     13     int to, next, cap, flow;
     14 }edge[MAXM];
     15 int tol;
     16 int head[MAXN];
     17 void init() 
     18 {
     19     tol = 2;
     20     memset(head, -1, sizeof(head));
     21 }
     22 void addedge(int u, int v, int w, int rw=0) 
     23 {
     24     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     25     edge[tol].next = head[u]; head[u] = tol++;
     26     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     27     edge[tol].next = head[v]; head[v] = tol++;
     28 }
     29 int Q[MAXN];
     30 int dep[MAXN], cur[MAXN], sta[MAXN];
     31 bool bfs(int s, int t, int n) 
     32 {
     33     int front = 0, tail = 0;
     34     memset(dep, -1, sizeof(dep[0])*(n+1));
     35     dep[s] = 0;
     36     Q[tail++] = s;
     37     while(front < tail)
     38     {
     39         int u = Q[front++];
     40         for(int i = head[u]; i != -1; i = edge[i].next) 
     41         {
     42             int v = edge[i].to;
     43             if(edge[i].cap > edge[i].flow && dep[v] == -1)                 {
     44                 dep[v] = dep[u] + 1;
     45                 if(v == t) return true;
     46                 Q[tail++] = v;
     47             }
     48         }
     49     }
     50     return false;
     51 }
     52 int dinic(int s, int t, int n) {
     53     int maxflow = 0;
     54     while(bfs(s, t, n)) {
     55         for(int i = 0; i < n; i++) cur[i] = head[i];
     56         int u = s, tail = 0;
     57         while(cur[s] != -1)
     58         {
     59             if(u == t) 
     60             {
     61                 int tp = INF;
     62                 for(int i = tail-1; i >= 0; i--)
     63                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     64                 maxflow+=tp;
     65                 for(int i = tail-1; i >= 0; i--) {
     66                     edge[sta[i]].flow+=tp;
     67                     edge[sta[i]^1].flow-=tp;
     68                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     69                         tail = i;
     70                 }
     71                 u = edge[sta[tail]^1].to;
     72             }
     73             else 
     74                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     75                 {
     76                     sta[tail++] = cur[u];
     77                     u = edge[cur[u]].to;
     78                 }
     79                 else 
     80                 {
     81                     while(u != s && cur[u] == -1)
     82                         u = edge[sta[--tail]^1].to;
     83                     cur[u] = edge[cur[u]].next;
     84                 }
     85         }
     86     }
     87     return maxflow;
     88 }
     89 int n,np,nc,m;
     90 char s[30];
     91 int u,v,z;
     92 int main()
     93 {
     94     while(~scanf("%d%d%d%d",&n,&np,&nc,&m))
     95     {
     96         init();
     97         for(int i=1;i<=m;++i)
     98         {
     99             scanf("%s",s);
    100             sscanf(s,"(%d,%d)%d",&u,&v,&z);
    101             addedge(u+1,v+1,z);
    102         }
    103         for(int i=1;i<=np;++i)
    104         {
    105             scanf("%s",s);
    106             sscanf(s,"(%d)%d",&u,&z);
    107             addedge(0,u+1,z);
    108         }
    109         for(int i=1;i<=nc;++i)
    110         {
    111             scanf("%s",s);
    112             sscanf(s,"(%d)%d",&u,&z);
    113             addedge(u+1,n+2,z);
    114         }
    115         cout<<dinic(0,n+2,n+3)<<endl;
    116     }
    117     return 0;
    118 }
    View Code

    G.    hdu4280     Island Transport

    分析:裸的最大流,但是由于边数比较多,容易超时和爆栈,我本来是存双向边的,T了好几发,修改了存边方式9000+ms水过。。。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int MAXN = 100010;
      8 const int MAXM = 1200012;
      9 const int INF = 0x3f3f3f3f;
     10 struct Edge 
     11 {
     12     int from,to, next, cap, flow;
     13 }edge[MAXM];
     14 int tol;
     15 int head[MAXN];
     16 void init() 
     17 {
     18     tol = 2;
     19     memset(head, -1, sizeof(head));
     20 }
     21 int min(int a,int b)
     22 {
     23 return a>b?b:a;
     24 }
     25 void addedge(int u, int v, int w, int rw=0) 
     26 {
     27         edge[tol].from=u;
     28     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     29     edge[tol].next = head[u]; head[u] = tol++;
     30 }
     31 int Q[MAXN];
     32 int dep[MAXN], cur[MAXN], sta[MAXN];
     33 bool bfs(int s, int t, int n) 
     34 {
     35     int front = 0, tail = 0;
     36     memset(dep, -1, sizeof(dep[0])*(n+1));
     37     dep[s] = 0;
     38     Q[tail++] = s;
     39     while(front < tail)
     40     {
     41         int u = Q[front++];
     42         for(int i = head[u]; i != -1; i = edge[i].next) 
     43         {
     44             int v = edge[i].to;
     45             if(edge[i].cap > edge[i].flow && dep[v] == -1)                 {
     46                 dep[v] = dep[u] + 1;
     47                 if(v == t) return true;
     48                 Q[tail++] = v;
     49             }
     50         }
     51     }
     52     return false;
     53 }
     54 int dinic(int s, int t, int n) {
     55     int maxflow = 0;
     56     while(bfs(s, t, n)) {
     57         for(int i = 0; i < n; i++) cur[i] = head[i];
     58         int u = s, tail = 0;
     59         while(cur[s] != -1)
     60         {
     61             if(u == t) 
     62             {
     63                 int tp = INF;
     64                 for(int i = tail-1; i >= 0; i--)
     65                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     66                 maxflow+=tp;
     67                 for(int i = tail-1; i >= 0; i--) {
     68                     edge[sta[i]].flow+=tp;
     69                     edge[sta[i]^1].flow-=tp;
     70                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     71                         tail = i;
     72                 }
     73                 u = edge[sta[tail]].from;
     74             }
     75             else 
     76                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     77                 {
     78                     sta[tail++] = cur[u];
     79                     u = edge[cur[u]].to;
     80                 }
     81                 else 
     82                 {
     83                     while(u != s && cur[u] == -1)
     84                         u = edge[sta[--tail]].from;
     85                     cur[u] = edge[cur[u]].next;
     86                 }
     87         }
     88     }
     89     return maxflow;
     90 }
     91 int n,m;
     92 struct Node
     93 {
     94     int x,y;
     95 }node[MAXN];
     96 
     97 int main()
     98 {
     99     int t;
    100     scanf("%d",&t);
    101     while(t--)
    102     {
    103         scanf("%d%d",&n,&m);
    104         Node a,b;
    105         init();
    106         int num1,num2;
    107         a.x=INF;
    108         b.x=-INF;
    109         for(int i=1;i<=n;++i)
    110         {
    111             int x,y;
    112             scanf("%d%d",&x,&y);
    113             if(x<a.x)
    114             {
    115                 a.x=x;
    116                 num1=i-1;
    117             }
    118             if(x>b.x)
    119             {
    120                 b.x=x;
    121                 num2=i-1;
    122             }
    123         }
    124         for(int i=1;i<=m;++i)
    125         {
    126             int u,v,c;
    127             scanf("%d%d%d",&u,&v,&c);
    128             addedge(u-1,v-1,c);
    129             addedge(v-1,u-1,c);
    130         }
    131         cout<<dinic(num1,num2,n)<<endl;
    132     }
    133     return 0;
    134 }
    135     
    View Code

    H.    hdu4292      Food

    分析:为了控制一个人只连一瓶饮料,一份食物,那么我们可以把一个人拆成两个,他们之间连一条权值为1的边,另外左边连它喜欢的食物,权值为1,右边连它喜欢的饮料,权值为1,在源点连食物的时候加流量限制,汇点加流量限制,跑一遍最大流即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int INF = 0x3f3f3f3f;
      8 const int MAXN = 1000;
      9 const int MAXM = 9000000;
     10 struct Edge 
     11 {
     12     int to, next, cap, flow;
     13 }edge[MAXM];
     14 int tol;
     15 int head[MAXN];
     16 void init() 
     17 {
     18     tol = 2;
     19     memset(head, -1, sizeof(head));
     20 }
     21 void addedge(int u, int v, int w, int rw=0) 
     22 {
     23     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     24     edge[tol].next = head[u]; head[u] = tol++;
     25     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     26     edge[tol].next = head[v]; head[v] = tol++;
     27 }
     28 int Q[MAXN];
     29 int dep[MAXN], cur[MAXN], sta[MAXN];
     30 bool bfs(int s, int t, int n) 
     31 {
     32     int front = 0, tail = 0;
     33     memset(dep, -1, sizeof(dep[0])*(n+1));
     34     dep[s] = 0;
     35     Q[tail++] = s;
     36     while(front < tail)
     37     {
     38         int u = Q[front++];
     39         for(int i = head[u]; i != -1; i = edge[i].next) 
     40         {
     41             int v = edge[i].to;
     42             if(edge[i].cap > edge[i].flow && dep[v] == -1)                         {
     43                 dep[v] = dep[u] + 1;
     44                 if(v == t) return true;
     45                 Q[tail++] = v;
     46             }
     47         }
     48     }
     49     return false;
     50 }
     51 int dinic(int s, int t, int n) {
     52     int maxflow = 0;
     53     while(bfs(s, t, n)) {
     54         for(int i = 0; i < n; i++) cur[i] = head[i];
     55         int u = s, tail = 0;
     56         while(cur[s] != -1)
     57         {
     58             if(u == t) 
     59             {
     60                 int tp = INF;
     61                 for(int i = tail-1; i >= 0; i--)
     62                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     63                 maxflow+=tp;
     64                 for(int i = tail-1; i >= 0; i--) {
     65                     edge[sta[i]].flow+=tp;
     66                     edge[sta[i]^1].flow-=tp;
     67                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     68                         tail = i;
     69                 }
     70                 u = edge[sta[tail]^1].to;
     71             }
     72             else 
     73                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     74                 {
     75                     sta[tail++] = cur[u];
     76                     u = edge[cur[u]].to;
     77                 }
     78                 else 
     79                 {
     80                     while(u != s && cur[u] == -1)
     81                         u = edge[sta[--tail]^1].to;
     82                     cur[u] = edge[cur[u]].next;
     83                 }
     84         }
     85     }
     86     return maxflow;
     87 }
     88 int num,n,f,d;
     89 char s[MAXN];
     90 
     91 int main()
     92 {
     93     while(~scanf("%d%d%d",&n,&f,&d))
     94     {
     95         init();
     96         for(int i=1;i<=f;++i)
     97         {
     98             scanf("%d",&num);
     99             addedge(0,i,num);
    100         }
    101         for(int i=1;i<=d;++i)
    102         {
    103             scanf("%d",&num);
    104             addedge(f+2*n+i,f+2*n+d+1,num);
    105         }
    106         for(int i=1;i<=n;++i)
    107         {
    108             addedge(f+i,f+n+i,1);
    109             scanf("%s",s);
    110             for(int j=1;j<=f;++j)
    111                 if(s[j-1]=='Y')
    112                     addedge(j,i+f,1);
    113         }
    114         for(int i=1;i<=n;++i)
    115         {
    116             scanf("%s",s);
    117             for(int j=1;j<=d;++j)
    118                 if(s[j-1]=='Y')
    119                     addedge(i+f+n,f+2*n+j,1);
    120         }
    121         cout<<dinic(0,f+2*n+d+1,f+2*n+d+2)<<endl;
    122     }
    123     return 0;
    124 }
    View Code

    I.     hdu4289    Control

    题意:给出一个由n个点,m条边组成的无向图。给出两个点s,t。对于图中的每个点,去掉这个点都需要一定的花费。求至少多少花费才能使得s和t之间不连通。

    分析:题意即求最小割,将每个点拆点,点与对应点的边权为去掉该点的花费,原图中所有边的边权赋为无穷大,跑一遍最大流即可。(最大流即最小割)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int MAXN = 2010;
      8 const int MAXM = 1200012;
      9 const int INF = 0x3f3f3f3f;
     10 struct Edge 
     11 {
     12     int to, next, cap, flow;
     13 }edge[MAXM];
     14 int tol;
     15 int head[MAXN];
     16 void init() 
     17 {
     18     tol = 2;
     19     memset(head, -1, sizeof(head));
     20 }
     21 void addedge(int u, int v, int w, int rw=0) 
     22 {
     23     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     24     edge[tol].next = head[u]; head[u] = tol++;
     25     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     26     edge[tol].next = head[v]; head[v] = tol++;
     27 }
     28 int Q[MAXN];
     29 int dep[MAXN], cur[MAXN], sta[MAXN];
     30 bool bfs(int s, int t, int n) 
     31 {
     32     int front = 0, tail = 0;
     33     memset(dep, -1, sizeof(dep[0])*(n+1));
     34     dep[s] = 0;
     35     Q[tail++] = s;
     36     while(front < tail)
     37     {
     38         int u = Q[front++];
     39         for(int i = head[u]; i != -1; i = edge[i].next) 
     40         {
     41             int v = edge[i].to;
     42             if(edge[i].cap > edge[i].flow && dep[v] == -1)                 {
     43                 dep[v] = dep[u] + 1;
     44                 if(v == t) return true;
     45                 Q[tail++] = v;
     46             }
     47         }
     48     }
     49     return false;
     50 }
     51 int dinic(int s, int t, int n) {
     52     int maxflow = 0;
     53     while(bfs(s, t, n)) {
     54         for(int i = 0; i < n; i++) cur[i] = head[i];
     55         int u = s, tail = 0;
     56         while(cur[s] != -1)
     57         {
     58             if(u == t) 
     59             {
     60                 int tp = INF;
     61                 for(int i = tail-1; i >= 0; i--)
     62                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     63                 maxflow+=tp;
     64                 for(int i = tail-1; i >= 0; i--) {
     65                     edge[sta[i]].flow+=tp;
     66                     edge[sta[i]^1].flow-=tp;
     67                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     68                         tail = i;
     69                 }
     70                 u = edge[sta[tail]^1].to;
     71             }
     72             else 
     73                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     74                 {
     75                     sta[tail++] = cur[u];
     76                     u = edge[cur[u]].to;
     77                 }
     78                 else 
     79                 {
     80                     while(u != s && cur[u] == -1)
     81                         u = edge[sta[--tail]^1].to;
     82                     cur[u] = edge[cur[u]].next;
     83                 }
     84         }
     85     }
     86     return maxflow;
     87 }
     88 int n,m,s,d;
     89 
     90 int main()
     91 {
     92     while(~scanf("%d%d",&n,&m))
     93     {
     94         init();
     95         scanf("%d%d",&s,&d);
     96         int c;
     97         for(int i=0;i<n;++i)
     98         {
     99             scanf("%d",&c);
    100             addedge(i,i+n,c);
    101         }
    102         for(int i=1;i<=m;++i)
    103         {
    104             int a,b;
    105             scanf("%d%d",&a,&b);
    106             addedge(a-1+n,b-1,INF);
    107             addedge(b-1+n,a-1,INF);
    108         }
    109         cout<<dinic(s-1,d-1+n,2*n)<<endl;
    110     }
    111     return 0;
    112 }
    View Code

    J.     UVA10480    Sabotage

    题意:旧政府有一个很庞大的网络系统,可以很方便的指挥他的城市,起义军为了减少伤亡所以决定破坏他们的网络,使他们的首都(1号城市)和最大的城市(2号城市)不能联

    系,不过破坏不同的网络所花费的代价是不同的,现在起义军想知道最少花费的代价是多少,输出需要破坏的线路。

    分析:与 I 题一样,也是求最小割,只要算出最大流即可。不过题目要求输出最小割的边,这也是可以用网络流解决的,方法:求完最大流后,在残留网络中从源点 s 开始 dfs ,将能

    到达的点标号( c - f >0 的边),最后遍历一遍边集,将起点被标记、终点未被标记的边输出。(注意这是无向图,边只用输出一遍,而在有向图中,条件应该改为起点标号、终点未标或起点未标、终点标号的边)。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 
      7 using namespace std;
      8 const int MAXN = 200;
      9 const int MAXM = 5000;
     10 const int INF = 0x3f3f3f3f;
     11 struct Edge 
     12 {
     13     int from,to, next, cap, flow;
     14 }edge[MAXM];
     15 int tol;
     16 int head[MAXN];
     17 void init() 
     18 {
     19     tol = 2;
     20     memset(head, -1, sizeof(head));
     21 }
     22 int min(int a,int b)
     23 {
     24     return a>b?b:a;
     25 }
     26 void addedge(int u, int v, int w, int rw=0) 
     27 {
     28     edge[tol].from=u;
     29     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     30     edge[tol].next = head[u]; head[u] = tol++;
     31 }
     32 int Q[MAXN];
     33 int dep[MAXN], cur[MAXN], sta[MAXN];
     34 bool bfs(int s, int t, int n) 
     35 {
     36     int front = 0, tail = 0;
     37     memset(dep, -1, sizeof(dep[0])*(n+1));
     38     dep[s] = 0;
     39     Q[tail++] = s;
     40     while(front < tail)
     41     {
     42         int u = Q[front++];
     43         for(int i = head[u]; i != -1; i = edge[i].next) 
     44         {
     45             int v = edge[i].to;
     46             if(edge[i].cap > edge[i].flow && dep[v] == -1)                         {
     47                 dep[v] = dep[u] + 1;
     48                 if(v == t) return true;
     49                 Q[tail++] = v;
     50             }
     51         }
     52     }
     53     return false;
     54 }
     55 int dinic(int s, int t, int n) {
     56     int maxflow = 0;
     57     while(bfs(s, t, n)) {
     58         for(int i = 0; i < n; i++) cur[i] = head[i];
     59         int u = s, tail = 0;
     60         while(cur[s] != -1)
     61         {
     62             if(u == t) 
     63             {
     64                 int tp = INF;
     65                 for(int i = tail-1; i >= 0; i--)
     66                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     67                 maxflow+=tp;
     68                 for(int i = tail-1; i >= 0; i--) {
     69                     edge[sta[i]].flow+=tp;
     70                     edge[sta[i]^1].flow-=tp;
     71                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     72                         tail = i;
     73                 }
     74                 u = edge[sta[tail]].from;
     75             }
     76             else 
     77                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     78                 {
     79                     sta[tail++] = cur[u];
     80                     u = edge[cur[u]].to;
     81                 }
     82                 else 
     83                 {
     84                     while(u != s && cur[u] == -1)
     85                         u = edge[sta[--tail]].from;
     86                     cur[u] = edge[cur[u]].next;
     87                 }
     88         }
     89     }
     90     return maxflow;
     91 }
     92 int n,m;
     93 bool vis[MAXN];
     94 
     95 void dfs(int u)
     96 {
     97     vis[u]=true;
     98     for(int i=head[u];i!=-1;i=edge[i].next)
     99     {
    100         int v=edge[i].to;
    101         if(edge[i].cap>edge[i].flow&&(!vis[v]))
    102                 dfs(v);
    103     }
    104 }
    105 
    106 int main()
    107 {
    108     while(~scanf("%d%d",&n,&m)&&n&&m)
    109     {
    110         init();
    111         for(int i=1;i<=m;++i)
    112         {
    113             int u,v,c;
    114             scanf("%d%d%d",&u,&v,&c);
    115             addedge(u-1,v-1,c);
    116             addedge(v-1,u-1,c);
    117         }
    118         dinic(0,1,n);
    119         memset(vis,false,sizeof(vis));
    120         dfs(0);
    121         for(int i=2;i<tol;i=i+2)
    122         {
    123             int u=edge[i].from;
    124             int v=edge[i].to;
    125             if(vis[u]!=vis[v])
    126             {
    127                 cout<<u+1<<" "<<v+1<<endl;
    128             }
    129         }
    130         cout<<endl;
    131     }
    132     return 0;
    133 }
    View Code

    K.     hdu2732     Leapin' Lizards

    题意:给你一个网格,网格上的一些位置上有一只蜥蜴,所有蜥蜴的最大跳跃距离是d,如果一只蜥蜴能跳出网格边缘,那么它就安全了。且每个网格有一个最大跳出次数x,即最多有x只蜥蜴从这个网格跳出,这个网格就再也不能有蜥蜴进来了。问你最少有多少只蜥蜴跳不出网格。

    分析:这是一道最大流。源点S编号0,网格的每个格子分成两个点i和i+n*m(n和m为网格的行和列数,i编号点是表示蜥蜴进来,而i+n*m编号的点是表示蜥蜴出去)。汇点t编号n*m*2+1。如果格子i上有蜥蜴,那么从s到i有边(s,i,1)。如果格子i能承受x次跳出,那么有边(i,i+n*m,x)。如果从格子i能直接跳出网格边界,那么有边(i+n*m,t,INF)。如果从格子i不能直接跳出网格,那么从i到离i距离<=d的网格j有边(i+n*m,j,INF),注意这里的距离是曼哈顿距离。最终我们求出的最大流就是能跳出网格的蜥蜴数。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int MAXN = 2010;
      8 const int MAXM = 1200012;
      9 const int INF = 0x3f3f3f3f;
     10 struct Edge 
     11 {
     12     int to, next, cap, flow;
     13 }edge[MAXM];
     14 int tol;
     15 int head[MAXN];
     16 void init() 
     17 {
     18     tol = 2;
     19     memset(head, -1, sizeof(head));
     20 }
     21 void addedge(int u, int v, int w, int rw=0) 
     22 {
     23     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     24     edge[tol].next = head[u]; head[u] = tol++;
     25     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     26     edge[tol].next = head[v]; head[v] = tol++;
     27 }
     28 int Q[MAXN];
     29 int dep[MAXN], cur[MAXN], sta[MAXN];
     30 bool bfs(int s, int t, int n) 
     31 {
     32     int front = 0, tail = 0;
     33     memset(dep, -1, sizeof(dep[0])*(n+1));
     34     dep[s] = 0;
     35     Q[tail++] = s;
     36     while(front < tail)
     37     {
     38         int u = Q[front++];
     39         for(int i = head[u]; i != -1; i = edge[i].next) 
     40         {
     41             int v = edge[i].to;
     42             if(edge[i].cap > edge[i].flow && dep[v] == -1)                 {
     43                 dep[v] = dep[u] + 1;
     44                 if(v == t) return true;
     45                 Q[tail++] = v;
     46             }
     47         }
     48     }
     49     return false;
     50 }
     51 int dinic(int s, int t, int n) {
     52     int maxflow = 0;
     53     while(bfs(s, t, n)) {
     54         for(int i = 0; i < n; i++) cur[i] = head[i];
     55         int u = s, tail = 0;
     56         while(cur[s] != -1)
     57         {
     58             if(u == t) 
     59             {
     60                 int tp = INF;
     61                 for(int i = tail-1; i >= 0; i--)
     62                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     63                 maxflow+=tp;
     64                 for(int i = tail-1; i >= 0; i--) {
     65                     edge[sta[i]].flow+=tp;
     66                     edge[sta[i]^1].flow-=tp;
     67                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     68                         tail = i;
     69                 }
     70                 u = edge[sta[tail]^1].to;
     71             }
     72             else 
     73                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     74                 {
     75                     sta[tail++] = cur[u];
     76                     u = edge[cur[u]].to;
     77                 }
     78                 else 
     79                 {
     80                     while(u != s && cur[u] == -1)
     81                         u = edge[sta[--tail]^1].to;
     82                     cur[u] = edge[cur[u]].next;
     83                 }
     84         }
     85     }
     86     return maxflow;
     87 }
     88 int t,n,d;
     89 char s[30];
     90 int map[30][30];
     91 
     92 int main()
     93 {
     94     int t;
     95     scanf("%d",&t);
     96     for(int k=1;k<=t;++k)
     97     {
     98         init();
     99         scanf("%d%d",&n,&d);
    100         memset(map,0,sizeof(map));
    101         scanf("%s",s);
    102         int m=strlen(s);
    103         for(int i=0;i<m;++i)
    104             map[1][i+1]=s[i]-'0';
    105         for(int i=2;i<=n;++i)
    106         {
    107             scanf("%s",s);
    108             for(int j=1;j<=m;++j)
    109                 map[i][j]=s[j-1]-'0';
    110         }
    111         int sum=0;
    112         for(int i=1;i<=n;++i)
    113         {
    114             scanf("%s",s);
    115             for(int j=1;j<=m;++j)
    116                 if(s[j-1]=='L')
    117                 {
    118                     sum++;
    119                     addedge(0,(i-1)*m+j,1);
    120                 }
    121         }
    122         for(int i=1;i<=n;++i)
    123             for(int j=1;j<=m;++j)
    124             {
    125                 int num=(i-1)*m+j;
    126                 if(map[i][j]==0)
    127                     continue;
    128                 addedge(num,num+n*m,map[i][j]);
    129                 if(i<=d||n-i<d||j<=d||m-j<d)
    130                     addedge(num+n*m,2*n*m+1,INF);
    131                 else
    132                 {
    133                     for(int a=1;a<=n;++a)
    134                         for(int b=1;b<=m;++b)
    135                         {
    136                             int id=(a-1)*m+b;
    137                             if(id==num)
    138                                 continue;
    139                             if(abs(i-a)+abs(j-b)<=d&&map[a][b]>0)
    140                                 addedge(num+n*m,id,INF);
    141                         }
    142                 }
    143             }
    144         int ans=sum-dinic(0,2*n*m+1,2*n*m+2);
    145         printf("Case #%d: ",k);
    146         if(ans==0)
    147             printf("no lizard was left behind.
    ");
    148         else
    149         {
    150             if(ans==1)
    151                 printf("1 lizard was left behind.
    ");
    152             else
    153                 printf("%d lizards were left behind.
    ",ans);
    154         }
    155     }
    156     return 0;
    157 }
    View Code

    L.      hdu3338      Kakuro Extension

    分析:这道题可以用网络流来做。以空白格为节点,假设流是从左流入,从上流出的,流入的容量为行和,流出来容量为列和,其余容量不变。求满足的最大流。由于流量有上下限限制,可以给每个数都减掉1,则填出来的数字范围为0—8, 就可以用单纯的网络流搞定了。求出来再加上就可以了。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int MAXN = 20100;
      8 const int MAXM = 1200012;
      9 const int INF = 0x3f3f3f3f;
     10 struct Edge 
     11 {
     12     int to, next, cap, flow;
     13 }edge[MAXM];
     14 int tol;
     15 int head[MAXN];
     16 void init() 
     17 {
     18     tol = 2;
     19     memset(head, -1, sizeof(head));
     20 }
     21 void addedge(int u, int v, int w, int rw=0) 
     22 {
     23     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     24     edge[tol].next = head[u]; head[u] = tol++;
     25     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     26     edge[tol].next = head[v]; head[v] = tol++;
     27 }
     28 int Q[MAXN];
     29 int dep[MAXN], cur[MAXN], sta[MAXN];
     30 bool bfs(int s, int t, int n) 
     31 {
     32     int front = 0, tail = 0;
     33     memset(dep, -1, sizeof(dep[0])*(n+1));
     34     dep[s] = 0;
     35     Q[tail++] = s;
     36     while(front < tail)
     37     {
     38         int u = Q[front++];
     39         for(int i = head[u]; i != -1; i = edge[i].next) 
     40         {
     41             int v = edge[i].to;
     42             if(edge[i].cap > edge[i].flow && dep[v] == -1)                         {
     43                 dep[v] = dep[u] + 1;
     44                 if(v == t) return true;
     45                 Q[tail++] = v;
     46             }
     47         }
     48     }
     49     return false;
     50 }
     51 int dinic(int s, int t, int n) {
     52     int maxflow = 0;
     53     while(bfs(s, t, n)) {
     54         for(int i = 0; i < n; i++) cur[i] = head[i];
     55         int u = s, tail = 0;
     56         while(cur[s] != -1)
     57         {
     58             if(u == t) 
     59             {
     60                 int tp = INF;
     61                 for(int i = tail-1; i >= 0; i--)
     62                     tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow);
     63                 maxflow+=tp;
     64                 for(int i = tail-1; i >= 0; i--) {
     65                     edge[sta[i]].flow+=tp;
     66                     edge[sta[i]^1].flow-=tp;
     67                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     68                         tail = i;
     69                 }
     70                 u = edge[sta[tail]^1].to;
     71             }
     72             else 
     73                 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 
     74                 {
     75                     sta[tail++] = cur[u];
     76                     u = edge[cur[u]].to;
     77                 }
     78                 else 
     79                 {
     80                     while(u != s && cur[u] == -1)
     81                         u = edge[sta[--tail]^1].to;
     82                     cur[u] = edge[cur[u]].next;
     83                 }
     84         }
     85     }
     86     return maxflow;
     87 }
     88 struct node
     89 {
     90     int x,y;
     91     int tmp;
     92 }s[11000],t[11000];
     93 int n,m;
     94 int a,b;
     95 int num[120][120][3],f[120][120];
     96 char str[100];
     97 
     98 int main()
     99 {
    100 while(~scanf("%d%d",&n,&m))
    101 {
    102     memset(num,0,sizeof(num));
    103     a=b=0;
    104     init();
    105     for(int i=1;i<=n;++i)
    106     {
    107         for(int j=1;j<=m;++j)
    108         {
    109             scanf("%s",str);
    110         //    int len=strlen(str);
    111             if(str[0]=='.') 
    112             {
    113                 num[i][j][0]=-1;
    114                 continue;
    115             }
    116             if(str[0]!='X')
    117             {
    118                 num[i][j][1]=(str[0]-'0')*100+(str[1]-'0')*10+str[2]-'0';
    119                 s[a].x=i;
    120                 s[a].y=j;
    121                 s[a++].tmp=num[i][j][1];
    122             }
    123             if(str[4]!='X')
    124             {
    125                 num[i][j][2]=(str[4]-'0')*100+(str[5]-'0')*10+str[6]-'0';
    126                 t[b].x=i;
    127                 t[b].y=j;
    128                 t[b++].tmp=num[i][j][2];
    129             }
    130         }
    131     }
    132 /*    for(int i=1;i<=n;++i)
    133     {
    134         for(int j=1;j<=m;++j)
    135         {
    136             cout<<num[i][j][0]<<"  "<<num[i][j][1]<<"  "<<num[i][j][2]<<"        ";
    137         }
    138         cout<<endl;
    139     }*/
    140     for(int i=0;i<a;++i)
    141     {
    142         int id=(s[i].x-1)*m+s[i].y;
    143     //    addedge(0,id,s[i].tmp); 
    144         int snum=0;
    145         for(int j=s[i].x+1;j<=n;++j)
    146         {
    147             if(num[j][s[i].y][0]==0)
    148                 break;
    149             int count=(j-1)*m+s[i].y;
    150             snum++;
    151             addedge(id,count,8);
    152         }
    153         addedge(0,id,s[i].tmp-snum);
    154     //    cout<<id<<"  "<<s[i].tmp-snum<<endl;
    155     }
    156     for(int i=0;i<b;++i)
    157     {
    158         int id=(t[i].x-1)*m+t[i].y+n*m;
    159     //    addedge(id,2*n*m+1,t[i].tmp);
    160         int tnum=0;
    161         for(int j=t[i].y+1;j<=m;++j)
    162         {
    163             if(num[t[i].x][j][0]==0)
    164                 break;
    165             int count=(t[i].x-1)*m+j;
    166             tnum++;
    167             addedge(count,id,8);
    168         }
    169         addedge(id,2*n*m+1,t[i].tmp-tnum);
    170     //    cout<<id<<"  "<<t[i].tmp-tnum<<endl;
    171     }
    172     int res=dinic(0,2*n*m+1,2*n*m+2);
    173 //    cout<<res<<endl;
    174     memset(f,0,sizeof(f));
    175     for(int i=2;i<tol;++i)
    176     {
    177         int c=edge[i].to;
    178         int y=c%m;
    179         if(y==0)
    180             y=m;
    181         int x=(c-y)/m+1;
    182     //    cout<<x<<" "<<y<<" "<<edge[i].flow<<endl;
    183         if(num[x][y][0]==-1&&edge[i].flow>0)
    184         {
    185         //    cout<<x<<" "<<y<<" "<<edge[i].flow<<endl;
    186             f[x][y]+=edge[i].flow;
    187         }
    188     }
    189     for(int i=1;i<=n;++i)
    190     {
    191         for(int j=1;j<=m;++j)
    192         {
    193             if(j!=1)
    194                 cout<<" ";
    195             if(num[i][j][0]==-1)
    196                 cout<<f[i][j]+1;
    197             else
    198                 cout<<"_";
    199         }
    200         cout<<endl;
    201     }
    202 }
    203      return 0;
    204 }
    View Code

    M.       hdu3605       Escape

    题意:这题题意很简单,现有n个人要移居到m个星球去,给定一个n*m的矩阵,第 i 行第 j 列如果为1,表示第 i 个人可以去第 j 个星球,如果为0,表示不可以去。

    分析:显然是个最大流问题,这题解题的关键在于建图,如果把每个人看做一个点,每个星球看做一个点,人到所有可以去的星球都连上边,那么整个图的边数在10^6,那么就会TLE,那么该怎么建图呢?注意到最多只有10个星球,如果两个人能够居住的星球的情况相同,则可以认为这两个人是同一类人,这样最多只有1024种人,点的数目大大减少,最后将每类人与适合这类人居住的星球建边跑最大流即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int MAXN = 201000;
      8 const int MAXM = 1200012;
      9 const int INF = 0x3f3f3f3f;
     10 struct Edge 
     11 {
     12     int to, next, cap, flow;
     13 }edge[MAXM];
     14 int tol;
     15 int head[MAXN];
     16 int gap[MAXN], dep[MAXN], cur[MAXN];
     17 int count[1200];
     18 void init() 
     19 {
     20     tol = 0;
     21     memset(head, -1, sizeof(head));
     22     memset(count,0,sizeof(count));
     23 }
     24 void addedge(int u, int v, int w, int rw = 0) 
     25 {
     26     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     27     edge[tol].next = head[u]; head[u] = tol++;
     28     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     29     edge[tol].next = head[v]; head[v] = tol++;
     30 }
     31 int Q[MAXN];
     32 void BFS(int start, int end) 
     33 {
     34     memset(dep, -1, sizeof(dep));
     35     memset(gap, 0, sizeof(gap));
     36     gap[0] = 1;
     37     int front = 0, rear = 0;
     38     dep[end] = 0;
     39     Q[rear++] = end;
     40     while(front != end) {
     41         int u = Q[front++];
     42         for(int i = head[u]; i != -1; i = edge[i].next) {
     43             int v = edge[i].to;
     44             if(dep[v] != -1) continue;
     45             Q[rear++] = v;
     46             dep[v] = dep[u] + 1;
     47             gap[dep[v]]++;
     48         }
     49     }
     50 }
     51 int S[MAXN];
     52 int sap(int start, int end, int N) {
     53     BFS(start, end);
     54     memcpy(cur, head, sizeof(head));
     55     int top = 0;
     56     int u = start;
     57     int ans = 0;
     58     while(dep[start] < N) 
     59     {
     60         if(u == end) 
     61         {
     62             int Min = INF;
     63             int inser;
     64             for(int i = 0; i < top; i++)
     65                 if(Min > edge[S[i]].cap - edge[S[i]].flow) {
     66                     Min = edge[S[i]].cap - edge[S[i]].flow;
     67                     inser = i;
     68                 }
     69             for(int i = 0; i < top; i++) 
     70             {
     71                 edge[S[i]].flow += Min;
     72                 edge[S[i]^1].flow -= Min;
     73             }
     74             ans += Min;
     75             top = inser;
     76             u = edge[S[top]^1].to;
     77             continue;
     78         }
     79         bool flag = false;
     80         int v;
     81         for(int i = cur[u]; i != -1; i = edge[i].next) 
     82         {
     83             v = edge[i].to;
     84             if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u])                 {
     85                 flag = true;
     86                 cur[u] = i;
     87                 break;
     88             }
     89         }
     90         if(flag) 
     91         {
     92             S[top++] = cur[u];
     93             u = v;
     94             continue;
     95         }
     96         int Min = N;
     97         for(int i = head[u]; i != -1; i = edge[i].next)
     98             if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) 
     99             {
    100                 Min = dep[edge[i].to];
    101                 cur[u] = i;
    102             }
    103         gap[dep[u]]--;
    104         if(!gap[dep[u]]) return ans;
    105         dep[u] = Min + 1;
    106         gap[dep[u]]++;
    107         if(u != start) u = edge[S[--top]^1].to;
    108     }
    109     return ans;
    110 }
    111 int n,m;
    112 int main()
    113 {
    114     while(~scanf("%d%d",&n,&m))
    115     {
    116         init();
    117         for(int i=1;i<=n;++i)
    118         {
    119             int num=0;
    120             int c=1;
    121             for(int j=1;j<=m;++j)
    122             {
    123                 int a;
    124                 scanf("%d",&a);
    125                 num+=c*a;
    126                 c=c*2;
    127             }
    128             count[num]++;
    129         }
    130         for(int i=0;i<1024;++i)
    131         {
    132             addedge(0,i+1,count[i]);
    133             int num=i;
    134             int j=1;
    135             while(num>0)
    136             {
    137                 int a=num%2;
    138                 if(a==1)
    139                     addedge(i+1,1024+j,count[i]);
    140                 num=num/2;
    141                 j++;
    142             }
    143         }
    144         for(int i=1;i<=m;++i)
    145         {
    146             int num;
    147             scanf("%d",&num);
    148             addedge(1024+i,1024+m+i,num);
    149             addedge(1024+m+i,1024+2*m+1,INF);
    150         }
    151         int ans=sap(0,1024+2*m+1,1024+2*m+2);
    152         if(ans==n)
    153             cout<<"YES"<<endl;
    154         else
    155             cout<<"NO"<<endl;
    156     }
    157     return 0;
    158 }
    View Code

    N.       hdu3081      Marriage Match II

    题解链接:http://www.cnblogs.com/yaoyueduzhen/p/5087404.html

    O.       hdu3416      Marriage Match IV

    题解链接:http://www.cnblogs.com/yaoyueduzhen/p/5089953.html

  • 相关阅读:
    线性动力学变分原理基础 Part1
    对分析动力学的一些理解
    Matlab数值求解超越方程的根
    FORTRAN数值求超越方程的根
    vim 基础操作
    a simple vim set for fortran
    g95 ld: cannot find crt1.o: No such file or directory
    ug中英文对照
    autocad一些快捷键和命令
    列选主元的高斯消元法的Fortran程序
  • 原文地址:https://www.cnblogs.com/yaoyueduzhen/p/5021756.html
Copyright © 2020-2023  润新知