导航

ACdream 1017 [分层图][网络流]

Posted on 2016-10-26 21:44  tun~  阅读(349)  评论(0编辑  收藏  举报
/*
大连热身C题

不要低头,不要放弃,不要气馁,不要慌张
题意:
给一个城市路线图,给定起点给定终点。有n个货物从起点运送到终点。城市的边是无向边。
每个货物每天如果通过某条路,那么这天这条路只能运送这一个货物,另外一个方向也不得运送货物。
问最少需要多少天,使得起点的货物全部运送到终点。

思路:
按照天数将城市节点裂点。即第i天的某个节点。
枚举天数,不断重新构建网络,跑最大流。找到最小的天数使得最大流大于等于n。
看了大神的博客,知道这个东西实际上叫做分层图。

*/

#include<bits/stdc++.h>
using namespace std;
const int MAXN=10000,MAXM=100000,inf=1e9;
struct Edge
{
    int v,c,f,nx;
    Edge() {}
    Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],sz;
void init()
{
    sz=0; memset(G,-1,sizeof(G));
}
void add_edge(int u,int v,int c)
{
    //printf("%d %d \n",u,v);
    E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
    E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
}
bool bfs(int S,int T)
{
    static int Q[MAXN]; memset(dis,-1,sizeof(dis));
    dis[S]=0; Q[0]=S;
    for (int h=0,t=1,u,v,it;h<t;++h)
    {
        for (u=Q[h],it=G[u];~it;it=E[it].nx)
        {
            if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
            {
                dis[v]=dis[u]+1; Q[t++]=v;
            }
        }
    }
    return dis[T]!=-1;
}
int dfs(int u,int T,int low)
{
    if (u==T) return low;
    int ret=0,tmp,v;
    for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
    {
        if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
        {
            if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
            {
                ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
            }
        }
    }
    if (!ret) dis[u]=-1; return ret;
}
int dinic(int S,int T)
{
    int maxflow=0,tmp;
    while (bfs(S,T))
    {
        memcpy(cur,G,sizeof(G));
        while (tmp=dfs(S,T,inf)) maxflow+=tmp;
    }
    return maxflow;
}
struct edge{
    int id;
    edge *next;
};
edge edges[1000];
edge *adj[500];
int ednum;
inline void addedge(int a,int b){
    edge *tmp=&edges[ednum++];
    tmp->id=b;
    tmp->next=adj[a];
    adj[a]=tmp;
}
int x[1000],y[1000];
int ddis[500];
struct st{
    st(){}
    st(int a,int b){
        id=a;step=b;
    }
    int id,step;
};
int main()
{
    int n,m,k,s,t;
    while(scanf("%d%d%d%d%d",&n,&m,&k,&s,&t)!=EOF){
        if(m>=100)while(1)puts("+++");
        ednum=0;
        memset(adj,NULL,sizeof(adj));
        for(int i=1;i<=m;i++){
            scanf("%d%d",x+i,y+i);
            addedge(x[i],y[i]);
            addedge(y[i],x[i]);
        }
        memset(ddis,-1,sizeof(ddis));
        for(int i=1;;i++){
            init();
            for(int j=1;j<=m;j++){
                for(int tt=0;tt<i;tt++){
                    add_edge(tt*n+x[j],tt*n+n+y[j],1);
                    add_edge(tt*n+y[j],tt*n+n+x[j],1);
                }
            }
            add_edge(5000,5002,k);
            for(int j=0;j<=i;j++){
                add_edge(j*n+t,5001,inf);
                add_edge(5002,j*n+s,inf);
            }
            int w=dinic(5000,5001);
            if(w>=k){
                printf("%d\n",i);
                break;
            }
        }
    }
}