LA 4597 网络流【有上下界】

来源:互联网 发布:魔侠传 网络导常检测 编辑:程序博客网 时间:2024/05/16 12:31
#include<cstring>#include<cstdio>#include<algorithm>#include<queue>#define pb push_back#define mp make_pair#define f1 first#define f2 secondusing namespace std;const int MAXN=110, inf=0x3f3f3f3f;struct ISAP{    struct Edge    {        int from,to,cap,flow,low,real;        Edge(){}        Edge(int a,int b,int c,int d,int e,int f):from(a),to(b),cap(c),flow(d),low(e),real(f){}    };    int n,m,s,t,ss,tt,lowtot;//结点数,边数(含反向弧),源点,汇点    vector<Edge> edges;//边表,edges[e]&edges[e^1]互为反向弧    vector<int> G[MAXN];//邻接表,G[i][j]表示结点i的第j条边在e数组中的序号    bool vis[MAXN];//BFS使用    int d[MAXN];//从起点到i的距离    int cur[MAXN];//当前弧下标    int p[MAXN];//可增广路上的上一条弧    int num[MAXN];//距离标号计数    void AddEdge(int from,int to,int cap,int low)//重边不影响    {   //printf("%d %d %d\n",from,to,cap);        edges.push_back(Edge(from,to,cap,0,low,1));        edges.push_back(Edge(to,from,0,0,low,0));//容量为0,表示反向弧        m=edges.size();        G[from].push_back(m-2);        G[to].push_back(m-1);    }    void add(int from,int to,int low,int ma)    {   lowtot+=low;        if (low==0) {AddEdge(from,to,ma,0);return;}        AddEdge(ss,to,low,0);        AddEdge(from,to,ma-low,low);        AddEdge(from,tt,low,0);    }    void init(int n)    {        this->n=n;ss=n-2;tt=n-1;        for(int i=0;i<n;++i) G[i].clear();        edges.clear();lowtot=0;    }    void BFS()//反向    {        memset(vis,0,sizeof(vis));        queue<int> Q;        Q.push(t);        d[t]=0;        vis[t]=1;        while(!Q.empty())        {            int x=Q.front();            Q.pop();            for(int i=0; i<G[x].size(); ++i)            {                Edge& e=edges[G[x][i]^1];                if(!vis[e.from]&&e.cap>e.flow)                {                    vis[e.from]=1;                    d[e.from]=d[x]+1;                    Q.push(e.from);                }            }        }    }    int Augment()    {        int x=t,a=inf;        while(x!=s)        {            Edge& e=edges[p[x]];            a=min(a,e.cap-e.flow);            x=edges[p[x]].from;        }        x=t;        while(x!=s)        {            edges[p[x]].flow+=a;            edges[p[x]^1].flow-=a;            x=edges[p[x]].from;        }        return a;    }    int Maxflow(int s,int t)//结点数    {        this->s=s,this->t=t;        int flow=0;        for (int i=0;i<n;i++)            d[i]=0; //!!!        memset(num,0,sizeof(num));        for(int i=0;i<n;++i) ++num[d[i]];//!!!        int x=s;        memset(cur,0,sizeof(cur));        while(d[s]<n)        {            if(x==t)            {                flow+=Augment();                x=s;            }            int ok=0;            for(int i=cur[x];i<G[x].size();++i)            {                Edge& e=edges[G[x][i]];                if(e.cap>e.flow&&d[x]==d[e.to]+1)//Advance                {                    ok=1;                    p[e.to]=G[x][i];                    cur[x]=i;                    x=e.to;                    break;                }            }            if(!ok)//Retreat            {                int m=n-1;                for(int i=0;i<G[x].size();++i)                {                    Edge& e=edges[G[x][i]];                    if(e.cap>e.flow) m=min(m,d[e.to]);                }                if(--num[d[x]]==0) break;//gap优化                num[d[x]=m+1]++;                cur[x]=0;                if(x!=s) x=edges[p[x]].from;            }        }        return flow;    }    vector<int> anss;    void dfs(int x)    {   anss.pb(x);        for(int i=0;i<G[x].size();++i)            {   Edge& e=edges[G[x][i]];                if (e.real&&e.low)                if (edges[G[x][i]-2].flow&&edges[G[x][i]+2].flow)                    {                       edges[G[x][i]-2].flow--;                       edges[G[x][i]+2].flow--;                       dfs(e.to);                       break;                    }            }    }    void solve(int left)    {   int size=edges.size();        int id=0;        for (int i=0;i<size;i++)               if (edges[i].real&&edges[i].low&&edges[i].flow)                {edges[i-2].flow+= edges[i].flow;                 edges[i+2].flow+= edges[i].flow;                }        for (int i=0;i<size;i++)            if (edges[i].from==0&&edges[i].real)            for (int j=0;j<edges[i].flow;j++)                {                    anss.clear();left--;                    dfs(edges[i].to);                    int anssize=anss.size();                    for (int ii=0;ii<anssize;ii++)                    printf("%d%c",anss[ii],(ii==anssize-1)?'\n':' ');                }    }}it;vector<pair<int,int > > aa;int n,pp;int ok(int mid,int ff=0){   int s=0,t=n+1;    it.init(t+3);    for (int i=1;i<=n;i++)    {it.AddEdge(s,i,inf,0);     it.AddEdge(i,t,inf,0);    }    it.AddEdge(t,s,mid,0);    for (int i=0;i<pp;i++)        it.add(aa[i].f1,aa[i].f2,1,inf);    int ans=it.Maxflow(t+1,t+2);    if (!ff)return ans>=it.lowtot; else return ans;}void doit(){    aa.clear();    for (int i=1,x,y;i<=n;i++)        {scanf("%d",&x);         while (x--)            {   scanf("%d",&y);                aa.pb(mp(i,y));            }        }    pp=aa.size();    int l=1,r=pp,mid,day; //r一开始为n,被自己2跪了    while (r>=l)        {            mid=(l+r)>>1;            if (ok(mid,0))     {day=mid; r=mid-1;}            else l=mid+1;        }    printf("%d\n",day);    int ans=ok(day,1);   // printf("flow=%d\n",ans);    it.solve(day);}int main(){    while(scanf("%d",&n)!=EOF)doit();    return 0;}/*61 31 31 42 5 6 00*/

0 0
原创粉丝点击