uva1324 - Bring Them There 网络流

By the year 3141, the human civilization has spread all over the galaxy. The special hypertunnels are usedto travel from one star system to another. To use the hypertunnel, you fly to a special location near thesource star using your spaceship, activate the hyperjumper, fly through the hypertunnel, get out near yourdestination star and fly to the planet you need. The whole process takes exactly one day. A small drawbackof the system is that for each tunnel every day only one spaceship can travel using this tunnel.

You are working in the transportation department of the ``Intergalaxy Business Machines" company. This morningyour boss has assigned a new task to you. To run the programming contest IBM needs to deliverK supercomputersfrom Earth where the company headquarters are located to the planet Eisiem. Since supercomputers are very large,one needs the whole spaceship to carry each supercomputer. You are asked to find a plan to deliver thesupercomputers that takes as few days as possible. Since IBM is a very powerful corporation, you may assumethat any time you need some tunnel for hyperjump, it is at your service. However, you still can use each tunnelonly once a day.

Input 

Input consists of several datasets. The first line of each dataset contains N - the number of star systems in the galaxy, M - the numberof tunnels, K - the number of supercomputers to be delivered,S - the number of the solar system (thesystem where planet Earth is) andT - the number of the star system where planet Eisiem is(2$ \le$N$ \le$50, 1$ \le$M$ \le$200, 1$ \le$K$ \le$50, 1$ \le$S,T$ \le$N,S $ \neq$T).

Next M lines contain two different integer numbers each and describe tunnels. For each tunnel the numbersof star systems that it connects are given. The tunnel can be traveled in both directions, but remember thateach day only one ship can travel through it, in particular, two ships cannot simultaneously travel throughthe same tunnel in opposite directions. No tunnel connects a star to itself and any two stars are connectedby at most one tunnel.

Output 

On the first line of the output for each dataset print L - the fewest number of days needed to deliverK supercomputersfrom star system S to star system T using hypertunnels. NextL lines must describe the process. Each linemust start withCi - the number of ships that travel from one system to another this day.Ci pairs ofinteger numbers must follow, pairA, B means that the ship number A travels from its current star system tostar system B.

It is guaranteed that there is a way to travel from star system S to star system T.

Sample Input 

6 7 4 1 6
1 2
2 3
3 5
5 6
1 4
4 6
4 3

Sample Output 

4
2 1 2 2 4
3 1 3 2 6 3 4
3 1 5 3 6 4 4
2 1 6 4 6

  有N个星球,任务是用最短的时间把K个计算机从星球S运送到T。星球中有M条双向路径,每条需要一天时间来通过,且不能有两艘飞船同时经过一条路径。每对星球之间最多只有一条路径。

  把每个点u拆成T+1个,ui表示经过i天之后的节点u。对于相邻节点a,b,在新图中添加ai->b(i+1),容量为1,bi->a(i+1)容量也为1。每天都求最大流,最大流达到K就退出,否则增大天数,也就是增加下一天的节点,构成新图之后在当前流量的基础上继续增广。

  记录每天有哪些流量,输出对应节点和路径,当天输出当天的,因为不可能会退流(只能从i天到i+1天),如果同时有ai->b(i+1)和bi->a(i+1)的流也没关系,这等价于ab都停着不动,不输出就行了。

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
#define INF 0x3f3f3f3f
#define eps 1e-9
#define MAXN 5010
#define MAXM 210
#define MAXNODE 105
#define MOD 100000
#define SIGMA_SIZE 4
typedef long long LL;
using namespace std;
int N,M,K,S,T,u[MAXM],v[MAXM];
struct Edge{
    int from,to,cap,flow;
};
struct Dinic{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[MAXN];
    bool vis[MAXN];
    int d[MAXN];
    int cur[MAXN];

    void clear_all(int n){
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }
    void clear_nodes(int a,int b){
        for(int i=a;i<b;i++) G[i].clear();
    }
    void add_edge(int from,int to,int cap){
        edges.push_back((Edge){from,to,cap,0});
        edges.push_back((Edge){to,from,0,0});
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    bool BFS(){
        memset(vis,0,sizeof(vis));
        queue<int> q;
        q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            int len=G[x].size();
            for(int i=0;i<len;i++){
                Edge& e=edges[G[x][i]];
                if(!vis[e.to]&&e.cap>e.flow){
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int DFS(int x,int a){
        if(x==t||a==0) return a;
        int flow=0,f,len=G[x].size();
        for(int& i=cur[x];i<len;i++){
            Edge& e=edges[G[x][i]];
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
                e.flow+=f;
                edges[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }
    int maxflow(int s,int t,int limit){
        this->s=s;
        this->t=t;
        int flow=0;
        while(BFS()){
            memset(cur,0,sizeof(cur));
            flow+=DFS(s,limit-flow);
            if(flow==limit) break;
        }
        return flow;
    }
}g;

int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d%d%d%d%d",&N,&M,&K,&S,&T)!=EOF){
        for(int i=0;i<M;i++) scanf("%d%d",&u[i],&v[i]);
        g.clear_all(N);
        int day=1,flow=0;
        for(;;){
            g.clear_nodes(day*N,(day+1)*N);
            for(int i=0;i<N;i++) g.add_edge((day-1)*N+i,day*N+i,INF);
            for(int i=0;i<M;i++){
                g.add_edge((day-1)*N+u[i]-1,day*N+v[i]-1,1);
                g.add_edge((day-1)*N+v[i]-1,day*N+u[i]-1,1);
            }
            flow+=g.maxflow(S-1,day*N+T-1,K-flow);
            if(flow==K) break;
            day++;
        }
        printf("%d\n",day);
        int idx=0;
        vector<int> location(K,S);
        for(int d=1;d<=day;d++){
            idx+=N*2;
            vector<int> moved(K, 0);
            vector<int> a,b;
            for(int i=0;i<M;i++){
                int f1=g.edges[idx].flow;
                idx+=2;
                int f2=g.edges[idx].flow;
                idx+=2;
                if(f1==1&&f2==0){
                    a.push_back(u[i]);
                    b.push_back(v[i]);
                }
                if(f1==0&&f2==1){
                    a.push_back(v[i]);
                    b.push_back(u[i]);
                }
            }
            printf("%d",a.size());
            int len=a.size();
            for(int i=0;i<len;i++){
                for(int j=0;j<K;j++) if(!moved[j]&&location[j]==a[i]){
                    printf(" %d %d", j+1, b[i]);
                    moved[j]=1;
                    location[j]=b[i];
                    break;
                }
            }
            printf("\n");
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值