POJ 1895 分层图网络流+输出路径

题意:
题目描述:在公元3141年人类的足迹已经遍布银河系。为了穿越那巨大的距离,人类发明了一种名为超时空轨道的技术。超时空轨道是双向的,连接两个星系,穿越轨道需要一天的时间。然而这个轨道只能同时给一艘飞船使用,也就是说,每条轨道每天只能有一艘飞船穿越。现在IBM公司要把K(K≤50)台超级计算机从地球运到Eisiem星系去,由于这些超级计算机个头巨大,一台计算机就要用一艘飞船来运。现在人类能够到达N(N≤50)个星系,拥有M(M≤200)条超时空轨道,太阳系的编号为S,Eisiem星系的编号为T。你需要求出至少需要几天才能将这些超级计算机全部运到目的地。注意,IBM公司是非常NB的公司,所有的超时空轨道都会优先给IBM公司使用。
思路:
这里写图片描述
这里写图片描述
From lydrainbowcat

//By SiriusRen
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 5555
#define M 444444
int n,m,k,from[N],to[N],jy,rec[N][55],rect[N][55],inf=0x3f3f3f3f;
int first[N],next[M],v[M],w[M],tot,T=5551,day,vis[N],ans;
void Add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void add(int x,int y,int z){Add(x,y,z),Add(y,x,0);}
bool tell(){
    memset(vis,-1,sizeof(vis)),vis[0]=0;
    queue<int>q;q.push(0);
    while(!q.empty()){
        int t=q.front();q.pop();
        for(int i=first[t];~i;i=next[i])
            if(w[i]&&vis[v[i]]==-1)
                vis[v[i]]=vis[t]+1,q.push(v[i]);
    }return vis[T]!=-1;
}
int zeng(int x,int y){
    if(x==T)return y;
    int r=0;
    for(int i=first[x];~i&&y>r;i=next[i])
        if(w[i]&&vis[v[i]]==vis[x]+1){
            int t=zeng(v[i],min(y-r,w[i]));
            w[i]-=t,w[i^1]+=t,r+=t;
        }
    if(!r)vis[x]=-1;
    return r;
}
void dfs(int x,int Day){
    for(int i=first[x];~i;i=next[i])
        if(w[i^1]){
            w[i]++,w[i^1]--;
            if(v[i]==T)return;
            if(v[i]==x+n)dfs(v[i],Day+1);
            else{
                rec[Day][0]++;
                rec[Day][rec[Day][0]]=jy;
                rect[Day][rec[Day][0]]=(v[i]-1)%n+1;
                dfs(v[i],Day+1); 
            }
            break;
        }
}
int main(){
    memset(first,-1,sizeof(first));
    scanf("%d%d%d%d%d",&n,&m,&k,&from[0],&to[0]);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&from[i],&to[i]);
    }add(0,from[0],k);
    day=0;
    while(++day){
        for(int i=1;i<=m;i++)add(from[i]+(day-1)*n,to[i]+day*n,1),add(to[i]+(day-1)*n,from[i]+day*n,1);
        for(int i=1;i<=n;i++)add(i+(day-1)*n,i+day*n,inf);
        add(to[0]+day*n,T,inf);
        while(tell())while(jy=zeng(0,inf))ans+=jy;
        if(ans==k){printf("%d
",day);break;}
    }
    for(jy=k;jy;jy--)dfs(0,0);
    for(int i=1;i<=day;i++){
        printf("%d ",rec[i][0]);
        for(int j=1;j<=rec[i][0];j++)
            printf("%d %d ",rec[i][j],rect[i][j]);
        putchar('
');
    }
}

这里写图片描述

原文地址:https://www.cnblogs.com/SiriusRen/p/6532140.html