• LA_6266 Admiral


    题意:求两条从s->t的路径,使得两条路径不能经过相同的点和边,且两条路径长度之和最小。

    其实一看到所有点和边只能经过一次,就很容易想到费用流了。拆点,将每个点拆i成(i,i')。对于原图中的每个点,连一条(i,i',1,0)的边,对于原图中的每条边(u,v),连一条(u',v,1,w)的边(w为边的权值),然后添加源S->i',cost=0,cap=2的边(S,i,2,0)的边,添加汇点T,同理,建一条(t,T,2,0)的边,跑一次最小费用最大流就可以得到答案了。

    其实这题很简单,但是我比赛的时候逗比了。。居然忘记了对源点容量的限制,另一方面我费用流写的确实太少了,要记住教训啊。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <queue>
      6 #define maxn 3000
      7 #define maxm 30000
      8 #define INF 1<<30
      9 using namespace std;
     10 
     11 struct ZKW_flow{
     12     int src,sink,e,n;
     13     int first[maxn];
     14     int cap[maxm],cost[maxm],v[maxm],next[maxm];
     15     void init(){
     16         e = 2;
     17         memset(first,-1,sizeof(first));
     18     }
     19 
     20     void add_edge(int a,int b,int cc,int ww){
     21         cap[e] = cc;cost[e] = ww;v[e] = b;
     22         next[e] = first[a];first[a] = e++;
     23         cap[e] = 0;cost[e] = -ww;v[e] = a;
     24         next[e] = first[b];first[b] = e++;
     25     }
     26 
     27     int d[maxn];
     28 
     29     void spfa(){
     30         for(int i = 1;i <= n;i++)   d[i] = INF;
     31         priority_queue<pair<int,int> > q;
     32         d[src] = 0;
     33         q.push(make_pair(0,src));
     34         while(!q.empty()){
     35             int u = q.top().second,dd = -q.top().first;
     36             q.pop();
     37             if(d[u] != dd)   continue;
     38             for(int i = first[u];i != -1;i = next[i]){
     39                 if(cap[i] && d[v[i]] > dd + cost[i]){
     40                     d[v[i]] = dd + cost[i];
     41                     q.push(make_pair(-d[v[i]],v[i]));
     42                 }
     43             }
     44         }
     45         for(int i = 1;i <= n;i++)   d[i] = d[sink] - d[i];
     46     }
     47 
     48     int Mincost,Maxflow;
     49     bool used[maxn];
     50 
     51     int add_flow(int u,int flow){
     52         if(u == sink){
     53             Maxflow += flow;
     54             Mincost += d[src] * flow;
     55             return flow;
     56         }
     57         used[u] = true;
     58         int now = flow;
     59         for(int i = first[u];i != -1;i = next[i]){
     60             int &vv = v[i];
     61             if(cap[i] && !used[vv] && d[u] == d[vv] + cost[i]){
     62                 int tmp = add_flow(vv,min(now,cap[i]));
     63                 cap[i] -= tmp;
     64                 cap[i^1] += tmp;
     65                 now -= tmp;
     66                 if(!now) break;
     67             }
     68         }
     69         return flow - now;
     70     }
     71 
     72     bool modify_label(){
     73         int dd = INF;
     74         for(int u = 1;u <= n;u++)   if(used[u])
     75             for(int i = first[u];i != -1;i = next[i]){
     76                 int &vv = v[i];
     77                 if(cap[i] && !used[vv]) dd = min(dd,d[vv] + cost[i] - d[u]);
     78             }
     79         if(dd == INF)    return false;
     80         for(int i = 1;i <= n;i++)   if(used[i]) d[i] += dd;
     81         return true;
     82     }
     83 
     84     int min_cost_flow(int ss,int tt,int nn){
     85         src = ss,sink = tt,n = nn;
     86         Mincost = Maxflow = 0;
     87         spfa();
     88         while(1){
     89             while(1){
     90                 for(int i = 1;i <= n;i++) used[i] = 0;
     91                 if(!add_flow(src,INF))  break;
     92             }
     93             if(!modify_label()) break;
     94         }
     95         return Mincost;
     96     }
     97 };
     98 
     99 ZKW_flow g;
    100 
    101 int main(){
    102     int n,m;
    103     while(scanf("%d%d",&n,&m) == 2){
    104         g.init();
    105         g.add_edge(1,1+n,2,0);
    106         g.add_edge(n,n+n,2,0);
    107         for(int i = 2;i < n;i++)
    108             g.add_edge(i,i+n,1,0);
    109         for(int i = 1;i <= m;i++){
    110             int a,b,c;
    111             scanf("%d%d%d",&a,&b,&c);
    112             g.add_edge(a+n,b,1,c);
    113         }
    114         int src = 2*n+1,sink = 2*n+2;
    115         g.add_edge(src,1,2,0);
    116         g.add_edge(2*n,sink,2,0);
    117         int ans = g.min_cost_flow(src,sink,sink+1);
    118         printf("%d
    ",ans);
    119     }
    120     return 0;
    121 }
    View Code
  • 相关阅读:
    星球基地
    手机评价
    2018
    mongoDB(Window)
    linux
    【整理】Java 11新特性总结
    【整理】Java 10新特性总结
    【整理】Java 9新特性总结
    【整理】Java 8新特性总结
    Java -- 内部类(二)
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3353611.html
Copyright © 2020-2023  润新知