#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;
}
HDU4971
最新推荐文章于 2016-07-27 21:47:00 发布