zoukankan      html  css  js  c++  java
  • bzoj 2324 [ZJOI2011]营救皮卡丘(floyd,费用流)

    2324: [ZJOI2011]营救皮卡丘

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1777  Solved: 712
    [Submit][Status][Discuss]

    Description

    皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路。

    火箭队一共有N个据点,据点之间存在M条双向道路。据点分别从1N标号。小智一行K人从真新镇出发,营救被困在N号据点的皮卡丘。为了方便起见,我们将真新镇视为0号据点,一开始K个人都在0号点。

    由于火箭队的重重布防,要想摧毁K号据点,必须按照顺序先摧毁1K-1号据点,并且,如果K-1号据点没有被摧毁,由于防御的连锁性,小智一行任何一个人进入据点K,都会被发现,并产生严重后果。因此,在K-1号据点被摧毁之前,任何人是不能够经过K号据点的。

    为了简化问题,我们忽略战斗环节,小智一行任何一个人经过K号据点即认为K号据点被摧毁。被摧毁的据点依然是可以被经过的。

    K个人是可以分头行动的,只要有任何一个人在K-1号据点被摧毁之后,经过K号据点,K号据点就被摧毁了。显然的,只要N号据点被摧毁,皮卡丘就得救了。

    野外的道路是不安全的,因此小智一行希望在摧毁N号据点救出皮卡丘的同时,使得K个人所经过的道路的长度总和最少。

    请你帮助小智设计一个最佳的营救方案吧!

     

    Input

    第一行包含三个正整数N,M,K。表示一共有N+1个据点,分别从0N编号,以及M条无向边。一开始小智一行共K个人均位于0号点。 

    接下来M行,每行三个非负整数,第i行的整数为Ai,Bi,Li。表示存在一条从Ai号据点到Bi号据点的长度为Li的道路。

    Output

    仅包含一个整数S,为营救皮卡丘所需要经过的最小的道路总和。

    Sample Input

    3 4 2
    0 1 1
    1 2 1
    2 3 100
    0 3 1

    Sample Output

    3
    【样例说明】
    小智和小霞一起前去营救皮卡丘。在最优方案中,小智先从真新镇前往1号点,接着前往2号据点。当小智成功摧毁2号据点之后,小霞从真新镇出发直接前往3号据点,救出皮卡丘。

    HINT

    对于100%的数据满足N ≤ 150, M ≤ 20 000, 1 ≤ K ≤ 10, Li ≤ 10 000, 保证小智一行一定能够救出皮卡丘。至于为什么K ≤ 10,你可以认为最终在小智的号召下,小智,小霞,小刚,小建,小遥,小胜,小光,艾莉丝,天桐,还有去日本旅游的黑猫警长,一同前去大战火箭队。

    Source

    【思路】

           Floyd+费用流。

           题目条件:1 每个点都必须经过 , 2 经过j时必须已经经过了0..j-1

           利用floyd求出对点之间的最短距,转化为DAG即保证条件2。求DAG上至多不超过k条的覆盖路。

           构图:每个点建立XY结点,连边(S,0,K,0)(S,Xi,1,0)(Yi,T,1,0),如果DAG上i,j之间有边,则连边(Xi,Yj,1,d[i][j])。

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<vector>
      5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
      6 using namespace std;
      7 
      8 typedef long long LL ;
      9 const int maxn = 800+10;
     10 const int INF = 1e9;
     11 
     12 struct Edge{ int u,v,cap,flow,cost;
     13 };
     14 struct zkw {
     15     int n,m,s,t;
     16     int vis[maxn],d[maxn];
     17     vector<int> G[maxn];
     18     vector<Edge> es;
     19     
     20     void init(int n) {
     21         this->n=n;
     22         es.clear();
     23         for(int i=0;i<n;i++) G[i].clear();
     24     }
     25     void AddEdge(int u,int v,int cap,int cost) {
     26         es.push_back((Edge){u,v,cap,0,cost});
     27         es.push_back((Edge){v,u,0,0,-cost});
     28         m=es.size();
     29         G[u].push_back(m-2);
     30         G[v].push_back(m-1);
     31     }
     32     bool spfa() {
     33         memset(vis,0,sizeof(vis));
     34         for(int i=0;i<n;i++) d[i]=INF;
     35         queue<int> q;
     36         d[t]=0 , vis[t]=1 , q.push(t);
     37         while(!q.empty()) {
     38             int u=q.front(); q.pop() , vis[u]=0;
     39             for(int i=0;i<G[u].size();i++) {
     40                 Edge& e=es[G[u][i]];
     41                 int v=e.v;
     42                 if(es[G[u][i]^1].cap && d[v]>d[u]-e.cost) {
     43                     d[v]=d[u]-e.cost;
     44                     if(!vis[v]) {
     45                         vis[v]=1;
     46                         q.push(v);
     47                     }
     48                 }
     49             }
     50         }
     51         return d[s]!=INF;
     52     }
     53     int dfs(int u,int a,LL& cost) {
     54         vis[u]=1;  if(u==t) return a;
     55         int used=0,w;
     56         for(int i=0;i<G[u].size();i++) {
     57             Edge& e=es[G[u][i]];
     58             int v=e.v;
     59             if(d[u]-e.cost==d[v] && !vis[v] && e.cap) {
     60                 w=dfs(v,min(a-used,e.cap),cost);
     61                 cost+=w*e.cost;
     62                 e.cap-=w , es[G[u][i]^1].cap+=w;
     63                 used+=w; if(used==a) return a;
     64             }
     65         }
     66         return used;
     67     }
     68     int Mincost(int s,int t,LL& cost) {
     69         this->s=s , this->t=t;
     70         int flow=0; cost=0;
     71         while(spfa()) {
     72             vis[t]=1;
     73             while(vis[t]) {
     74                 memset(vis,0,sizeof(vis));
     75                 flow+=dfs(s,INF,cost);
     76             }
     77         }
     78         return flow;
     79     }
     80 } mc;
     81 
     82 int n,m,K;
     83 int d[maxn][maxn]; 
     84 
     85 int main() {
     86     scanf("%d%d%d",&n,&m,&K);
     87     mc.init(n+n+4);
     88     int s=n+n+2,t=s+1;
     89     int u,v,w;
     90     FOR(i,0,n) FOR(j,0,n) d[i][j]=INF;
     91     FOR(i,1,m) {
     92         scanf("%d%d%d",&u,&v,&w);
     93         d[u][v]=d[v][u]=min(d[u][v],w);        //重边 
     94     }
     95     FOR(k,0,n) FOR(i,0,n) FOR(j,0,n)
     96         if(k<=j || k<=i)  d[i][j]=min(d[i][k]+d[k][j],d[i][j]);
     97     mc.AddEdge(s,n+1,K,0);
     98     FOR(i,1,n) {
     99         mc.AddEdge(s,i+n+1,1,0);
    100         mc.AddEdge(i,t,1,0);
    101     }
    102     FOR(i,0,n) FOR(j,i+1,n)
    103         if(d[i][j]!=INF)  mc.AddEdge(i+n+1,j,1,d[i][j]);
    104     LL cost;
    105     mc.Mincost(s,t,cost);
    106     printf("%lld",cost);
    107     return 0;
    108 }
  • 相关阅读:
    监控里的主码流和子码流是什么意思
    监控硬盘容量计算
    一个能让你了解所有函数调用顺序的Android库
    电工选线
    oracle linux dtrace
    list all of the Oracle 12c hidden undocumented parameters
    Oracle Extended Tracing
    window 驱动开发
    win7 x64 dtrace
    How to Use Dtrace Tracing Ruby Executing
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5095769.html
Copyright © 2011-2022 走看看