HDU4971

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#define maxn 10010
#define INF 9999999//过了,一个是建图的思想,要想到是最大权闭合图,一个是模版,要套用好的模版,不断精进 
using namespace std;

struct EDGE
{
	int u,v,cap,next;
}edge[maxn];
int head[maxn],dist[maxn],cur[maxn],s[maxn],que[maxn];
int source,dest,edgenum,flow;

void add_edge(int u,int v,int cap)
{
	edge[edgenum].u=u;
	edge[edgenum].v=v;
	edge[edgenum].cap=cap;
	edge[edgenum].next=head[u];
	head[u]=edgenum;
	edgenum++;
	edge[edgenum].u=v;
	edge[edgenum].v=u;
	edge[edgenum].cap=0;
	edge[edgenum].next=head[v];
	head[v]=edgenum;
	edgenum++;
}


 
int bfs()
{
    int front = 0;//队头 
    int rear = 1;//队尾 
    memset(dist, -1, sizeof(dist));
    dist[source] = 0;
    que[front] = source;
    while (front < rear)
	 {
        int cnt = que[front];//遍历这个点的所有下边 
        for (int i = head[cnt]; i != -1; i = edge[i].next)
		{
            int v = edge[i].v;
            if (edge[i].cap > 0 && dist[v] == -1) 
			{
                dist[v] = dist[cnt] + 1;//这是深度么,流量为正的边的终点dist++ 
                que[rear++] = v;//入队列 
                if (v == dest) //为终点则return 
				{
                    return 1;
                }
            }
        }
        front++;
    }
    return 0;
}



int dinic() 
{
    int top, cnt, min_flow, min_flow_num, flow;
    flow = 0;
    while (bfs())//这是找到一条增广路的意思么 
	{
        memcpy(cur, head, sizeof(cur));
        top = 0;
        cnt = source;
        while (1) 
		{
            if (cnt == dest)
			 {
                min_flow = INF;
                for (int i = 0; i < top; i++) //找符合条件的增广流量 
				{
                    if (edge[s[i]].cap < min_flow) 
					{
                        min_flow = edge[s[i]].cap;
                        min_flow_num = i;
                    }
                }
                for (int i = 0; i < top; i++) //更新流量 
				{
                   edge[s[i]].cap -= min_flow;
                   edge[s[i] ^ 1].cap += min_flow;
                }
                flow += min_flow;//flow为最终的最大流值 
                top = min_flow_num;
                cnt = edge[s[top]].u;
            }
            for (int i = cur[cnt]; i != -1; cur[cnt] = i = edge[i].next)
			{
                if (edge[i].cap > 0 && dist[edge[i].v] == dist[cnt] + 1) 
				{
                    break;
                }
            }
            if (cur[cnt] != -1) //所以说s数组的赋值居然在这里是么 
			{
                s[top++] = cur[cnt];
                cnt = edge[cur[cnt]].v;
            }
            else 
			{
                if (top == 0) 
				{
                    break;
                }
                dist[cnt] = -1;
                top--;
                cnt = edge[s[top]].u;
            }
        }
    }
    return flow;
}



int main()
{
	int CAS;
	scanf("%d",&CAS);
	for(int kcas=1;kcas<=CAS;kcas++)
	{
		int n,m;
		int sum=0; 
		cin>>n>>m;
		edgenum= 0;
        memset(head, -1, sizeof(head));//一堆的初始化问题 
        source = 0;
        dest = n + m + 1;
		for(int i=1;i<=n;i++)
		{
			int x;
			cin>>x;sum+=x; 
			add_edge(source,i,x);
		}
		for(int i=1;i<=m;i++)
		{
			int y;
			cin>>y;
			add_edge(n+i,dest,y);
		} 
		for(int i=1;i<=n;i++)
		{
			int a;
			cin>>a;
			for(int j=1;j<=a;j++)
			{
				int x;
				cin>>x;
				add_edge(i,n+x+1,INF);//问题的序号是从零开始的 
			}
		} 
		for(int i=1;i<=m;i++)
		{
			for(int j=1;j<=m;j++)
			{
				int grid;
				cin>>grid;
				if(grid)
				{
					add_edge(n+i,n+j,INF);
				}
			}
		}
		/*******到此为止边建完了 */
		int res=dinic();//还不如用人家的dinic模板呢 
		int result=sum-res;
		printf("Case #%d: %d\n", kcas, result);
	}
	return 0;
} 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值