zoukankan      html  css  js  c++  java
  • [zoj] 3229 Shoot the Bullet || 有源汇上下界最大流

    zoj

    文文要给幻想乡的女孩子们拍照,一共n天,m个女孩子,每天文文至多拍D[i]张照片,每个女孩子总共要被文文至少拍G[i]次。在第i天,文文可以拍c[i]个女孩子,c[i]个女孩子中每个女孩子在当天被拍的次数是[l,r],求最多可以拍多少张照片,以及每天每个可以拍的女孩子被拍了多少张照片。


    有源汇上下界最大流。

    先跑有源汇上下界可行流,判断是否可行,若可行则此时跑原图中s到t的最大流即为答案。
    //代码与题解不符……

    #include<cstdio>
    #include<algorithm>
    #define N 2010
    #define M 100010
    #define inf 0x3f3f3f3f
    using namespace std;
    struct hhh
    {
        int to,w,next,num;
    }edge[M];
    int cnt=1,head[N],dis[N],cur[N],tot;
    int n,m,s,t,ss,tt,sum,q[N],r,ans[M],extra[N],x,y,low[M];
    
    int read()
    {
        int ans=0,fu=1;
        char j=getchar();
        for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
        for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
        return ans*fu;
    }
    
    void init()
    {
        s=0;t=n+m+1;
        ss=t+1;tt=t+2;
        sum=tot=0;
        cnt=2;
        for (int i=s;i<=tt;i++)
    	extra[i]=head[i]=0;
    }
    
    void add(int u,int v,int w,int num)
    {
        edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;edge[cnt].num=num;head[u]=cnt++;
        edge[cnt].to=u;edge[cnt].next=head[v];edge[cnt].w=0;edge[cnt].num=num;head[v]=cnt++;    
    }
    
    void ADD(int u,int v,int b,int c,int num)
    {
        extra[u]-=b;
        extra[v]+=b;
        add(u,v,c-b,num);
    }
    
    bool bfs(int S,int T)
    {
        for (int i=0;i<=n+m+3;i++)
    	cur[i]=head[i],dis[i]=-1;
        dis[S]=1;
        q[r=1]=S;
        for (int l=1;l<=r;l++)
        {
    	int u=q[l];
    	for (int i=head[u],v;i;i=edge[i].next)
    	    if (edge[i].w && dis[v=edge[i].to]==-1)
    	    {
    		dis[v]=dis[u]+1;
    		q[++r]=v;
    		if (v==T) return 1;
    	    }
        }
        return 0;
    }
    
    int dfs(int u,int flow,int T)
    {
        if (u==T) return flow;
        int ret=0,delta;
        for (int &i=cur[u],v;i;i=edge[i].next)
    	if (edge[i].w && dis[v=edge[i].to]==dis[u]+1)
    	{
    	    delta=dfs(v,min(edge[i].w,flow-ret),T);
    	    if (delta)
    	    {
    		edge[i].w-=delta;
    		edge[i^1].w+=delta;
    		ret+=delta;
    		if (ret==flow) break;
    	    }
    	}
        return ret;
    }
    
    int dinic(int S,int T)
    {
        int ans=0;
        while (bfs(S,T))
    	ans+=dfs(S,inf,T);
        return ans;
    }
    
    int main()
    {
        while (~scanf("%d%d",&n,&m))
        {
    	init();
    	for (int i=1;i<=m;i++)
    	{
    	    x=read();
    	    ADD(n+i,t,x,inf,0);
    	}
    	for (int i=1;i<=n;i++)
    	{
    	    x=read();y=read();
    	    ADD(s,i,0,y,0);
    	    for (int j=1,l,h;j<=x;j++)
    	    {
    		++tot;
    		y=read();l=read();h=read();
    		ADD(i,n+y+1,l,h,tot);
    		low[tot]=l;
    	    }
    	}
    	for (int i=s;i<=t;i++)
    	{
    	    if (extra[i]>0) add(ss,i,extra[i],0),sum+=extra[i];
    	    if (extra[i]<0) add(i,tt,-extra[i],0);
    	}
    	add(t,s,inf,0);
    	if (dinic(ss,tt)==sum)
    	{
    	    for (int i=head[ss];i;i=edge[i].next)
    		edge[i].w=edge[i^1].w=0;
    	    for (int i=head[tt];i;i=edge[i].next)
    		edge[i].w=edge[i^1].w=0;
    	    int flow=edge[cnt-1].w;
    	    edge[cnt-1].w=edge[cnt-2].w=0;
    	    printf("%d
    ",flow+dinic(s,t));
    	    for (int i=1;i<=m;i++)
    		for (int j=head[i+n];j;j=edge[j].next)
    		    if (edge[j].num!=0)
    			ans[edge[j].num]=edge[j].w+low[edge[j].num];
    	    for (int i=1;i<=tot;i++)
    		printf("%d
    ",ans[i]);
    	}
    	else printf("-1
    ");
    	putchar('
    ');
        }
        return 0;
    }
    
  • 相关阅读:
    HDU Problem 1811 Rank of Tetris【拓扑排序+并查集】
    POJ Problem 2367 Genealogical tree【拓扑排序】
    HDU Problem 2647 Reward【拓扑排序】
    HDU Problem 1285 确定比赛名次【拓扑排序】
    HDU Problem HDU Today 【最短路】
    HDU Problem 3665 Seaside【最短路】
    HDU Problem 一个人的旅行 【最短路dijkstra】
    HDU Problem 1596 find the safest road【最短路dijkstra】
    Beyond Compare文本合并进行内容替换要注意什么
    用这些工具都可以比较代码的差异
  • 原文地址:https://www.cnblogs.com/mrha/p/8227691.html
Copyright © 2011-2022 走看看